2010-08-06 2 views
9

Sono praticamente grepping con un'espressione regolare su. Nell'output, mi piacerebbe vedere solo le stringhe che corrispondono al mio exp del registro.In grep su Ubuntu, come posso visualizzare solo la stringa che corrisponde all'espressione regolare?

In un gruppo di file XML (principalmente sono file a riga singola con enormi quantità di dati in una riga), mi piacerebbe ottenere tutte le parole che iniziano con MAIL_.

Inoltre, vorrei che il comando grep sulla shell fornisse solo le parole corrispondenti e non l'intera riga (che è l'intero file in questo caso).

Come posso fare?

ho cercato

grep -Gril MAIL_* . 
grep -Grio MAIL_* . 
grep -Gro MAIL_* . 

risposta

13

Prima di tutto, con GNU grep installato con Ubuntu, il flag -G (usa regexp di base) è l'impostazione predefinita, quindi è possibile ometterlo, ma, ancora meglio, utilizzare regexp estesa con -E.

-r flag indica la ricerca ricorsiva all'interno dei file di una directory, questo è quello che ti serve.

E, hai ragione di usare -un flag per stampare la parte corrispondente di una linea. Inoltre, per omettere i nomi dei file è necessario un flag -h.

L'unico errore che hai fatto è la stessa espressione regolare. Hai perso la specifica del personaggio prima *. Il comando dovrebbe essere simile a questo:

grep -Ehro 'MAIL_[^[:space:]]*' . 

uscita del campione (non ricorsiva):

$ echo "Some garbage MAIL_OPTION comes MAIL_VALUE here" | grep -Eho 'MAIL_[^[:space:]]*' 
MAIL_OPTION 
MAIL_VALUE 
+0

great..that funziona, ma una domanda veloce come faccio se so che il MAIL_ * roba sono presenti come type = "MAIL_ *" o> MAIL _ * AMM

+0

Non capisco. Potresti riformulare la tua domanda? Vuoi vedere i personaggi circostanti attorno alle tue cose MAIL_XXX? Come, vuoi vedere "e <> nell'output del comando grep? – thor

+0

se il tuo MAIL_ * potrebbe contenere solo caratteri alfabetici (a-z), allora puoi cambiare regexp in" MAIL _ [[: alpha:]] * ' – thor

2
grep -o or --only-matching 

uscite solo il testo corrispondente al posto di linee complete, ma il problema potrebbe essere la vostra espressione regolare che non è restrittiva o abbastanza avido e in realtà corrisponde l'intero file.

+0

ora il tipo di parole che voglio sono presenti come questo nel file type = "MAIL_ABC_CDE" type = "MAIL_XXX_AAA_AAA" ecc ci può essere un numero qualsiasi di _ WHAT dovrebbe essere il reg exp exp shoudl utilizzare? qualche idea al riguardo? – AMM

5

Provate il seguente comando

grep -Eo 'MAIL_[[:alnum:]_]*' 
0

Dal tuo commento alla risposta di Thor ti sembra anche voler per distinguere se il testo MAIL_.* è un nodo di testo o un attributo, non solo per isolarlo ogni volta che appare nel documento XML. Grep non può analizzare XML, you need a proper XML parser for that.

Un parser xml da riga di comando è xmlstarlet. È confezionato in Ubuntu.

Usando su questo esempio esempio file:

$ cat test.xml 
<some_root> 
    <test a="MAIL_as_attribute">will be printed if you want matching attributes</test> 
    <bar>MAIL_as_text will be printed if you want matching text nodes</bar> 
    <MAIL_will_not_be_printed>abc</MAIL_will_not_be_printed> 
</some_root> 

per la selezione di nodi di testo è possibile utilizzare:

$ xmlstarlet sel -t -m '//*' -v 'text()' -n test.xml | grep -Eo 'MAIL_[^[:space:]]*' 
MAIL_as_text 

E per gli attributi selezione:

$ xmlstarlet sel -t -m '//*[@*]' -v '@*' -n test.xml | grep -Eo 'MAIL_[^[:space:]]*' 
MAIL_as_attribute 

una breve spiegazione:

  • //* è un'espressione XPath che seleziona tutti gli elementi nel documento e text() emette il valore delle loro nodi di testo figli, quindi tutto tranne i nodi di testo viene filtrato
  • //*[@*] è un'espressione XPath che seleziona tutti gli attributi del documento e poi @* emette il loro valore