Como extrair apenas uma parte de uma linha?

2

Eu quero extrair o essid em um arquivo de despejo do airodump-ng usando grep. A parte em que quero extrair se parece com isso:

    <SSID first-time="Wed Feb 25 07:06:57 2015" last-time="Wed Feb 25 07:14:23 2015">
        <type>Beacon</type>
        <max-rate>54.000000</max-rate>
        <packets>3371</packets>
        <beaconrate>10</beaconrate>
        <encryption>WPA2 AES-CCM </encryption>
        <essid cloaked="false">WLAN-123651234</essid>
    </SSID>
    <BSSID>24:65:11:3A:68:02</BSSID>
    <manuf>Unknown</manuf>
    <channel>1</channel>
    <freqmhz>2412 23193</freqmhz>
    <maxseenrate>54000</maxseenrate>
    <packets>

Então eu quero extrair o essid "WLAN-123651234" na linha 7. Como faço isso? E não importa quanto tempo o essid seja porque eu quero usar dessa maneira não apenas para esse essid, então ele precisa ser extraído assim:

grep >....< dumpfile.netxml
Output: WLAN-1234651234
    
por Nroh 28.02.2015 / 11:14

4 respostas

4

Com o GNU grep vinculado a uma versão recente da biblioteca PCRE (Perl Compatible Regular Expressions), você pode tentar:

$ grep -oP '<essid\b[^<>]*>\K[^<>]*(?=</essid>)' file
WLAN-123651234

Isso extrairia o conteúdo da tag essid .

Explicação:

  • <essid corresponde exatamente à string <essid

  • \b limite de palavra que corresponde entre um caractere de palavra e um caractere de não palavra, vice-versa.

  • [^<>]* classe de caractere negada que corresponde a qualquer caractere, mas não a < ou > , zero ou mais vezes.

  • \K descarta todos os caracteres previamente correspondidos da impressão na final.

  • [^<>]* classe de caractere negada que corresponde a qualquer caractere, mas não a < ou > , zero ou mais vezes.

  • (?=</essid>) Asserção antecipada positiva que afirma que a correspondência deve ser seguida pela string </essid> .

por 28.02.2015 / 11:18
4

Por que você está usando o grep para extrair material de arquivos xml? Você está usando o grep, então provavelmente você está em um sistema Linux ou BSD, então por que não usar o xpath da linha de comando?

xpath -q -e "SSID/essid/text()" /path/to/file.xml

Faz exatamente o que você quer, e com muito menos problemas do que uma expressão regular, que tendem a ser frágeis em extrair material do XML.

Se não estiver instalado, o seu gerenciador de pacotes deve ser capaz de cuidar dele. No Ubuntu, o pacote relevante é chamado libxml-xpath-perl .

    
por 28.02.2015 / 16:37
2

Com o GNU grep:

grep -oP 'essid.*>\K.*(?=<)' file

Saída:

WLAN-123651234
    
por 28.02.2015 / 12:13
1

Em risco de soar como um registro quebrado - XML é uma estrutura de dados, e há uma variedade de coisas que podem ser feitas nessa estrutura de dados que são válidas até onde a especificação XML vai, mas que a quebra completamente no que diz respeito às expressões regulares. Coisas como formatação de linha, indentação, quebra automática de tags etc.

Por isso, recomendo a todos que, ao processar XML, usem um analisador XML. Eles são projetados para manipular o aninhamento e o processamento de XML que ignora o formato, mas ainda diferencia semântica importante como tags, aninhamento e atributos.

Então eu abordaria seu problema assim:

#!/usr/local/bin/perl

use strict;
use warnings;
use XML::Twig;

XML::Twig->new(
    'twig_handlers' => {
        'essid' => sub { print $_ ->text }
    }
)->parse( <> );

Isso vai cuspir:

WLAN-123651234

E se você estiver interessado em não ter um arquivo de script separado (mas acho que deveria, porque geralmente é melhor para maior clareza e manutenção), você pode reduzir ainda mais:

perl -MXML::Twig -e 'XML::Twig->new( twig_handlers => { essid => sub { print $_ -> text,"\n" } } ) -> parse ( <> );' 

Para pontos de bônus - você pode usar expressões xpath xpath como:

essid[@cloaked="false"] 

Para imprimir um subconjunto.

Utilmente também - XML::Twig module vem com o utilitário xml_grep muito útil que ... faz exatamente o que você quer, em que ele vai grep grep.

    
por 18.06.2015 / 11:20