2010-08-06 11 views
9

Jestem w zasadzie grepping z wyrażeniem regularnym na. Na wyjściu chciałbym zobaczyć tylko ciągi pasujące do mojego reg exp.W grep na Ubuntu, jak mogę wyświetlić tylko ciąg, który pasował do wyrażenia regularnego?

W wielu plikach XML (przeważnie są to pliki jednoliniowe z ogromnymi ilościami danych w wierszu), chciałbym uzyskać wszystkie słowa rozpoczynające się od MAIL_.

Chciałbym również, aby polecenie grep na powłoce dało tylko wyrazy pasujące, a nie całą linię (w tym przypadku cały plik).

Jak to zrobić?

Próbowałem

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

Odpowiedz

13

Po pierwsze, z GNU grep, który jest instalowany z Ubuntu, flaga -G (użyj podstawowego wyrażenia regularnego) jest domyślna, więc możesz ją pominąć, ale, jeszcze lepiej, użyj rozszerzonego regexp z opcją -E.

-r flaga oznacza wyszukiwanie rekurencyjne w plikach katalogu, to jest to, czego potrzebujesz.

I masz rację, używając opcji -o, aby wydrukować pasującą część linii. Aby pominąć nazwy plików, potrzebujesz flagi -h.

Jedyny błąd, jaki popełniłeś, to wyrażenie regularne. Opuściłeś specyfikację postaci przed *. Twoje polecenie powinno wyglądać następująco:

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

Przykładowe wyjście (nie rekurencyjne):

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

świetnie .. to działa, ale jedno szybkie pytanie jak mam zrobić, jeśli wiem, że rzeczy MAIL_ * są obecne jako typ = "MAIL_ *" lub> MAIL _ * AMM

+0

Nie rozumiem tego. Czy mógłbyś przeformułować swoje pytanie? Chcesz zobaczyć otaczające Cię postacie wokół swoich rzeczy MAIL_XXX? Na przykład, chcesz zobaczyć "i <> w komendzie polecenia grep? – thor

+0

, jeśli twój MAIL_ * może zawierać tylko znaki alfabetyczne (a-z), możesz zmienić wyrażenie regularne na" MAIL _ [[: alpha:]] * " – thor

2
grep -o or --only-matching 

wyjść tylko pasujący tekst zamiast kompletnych linii, ale problem może być Twój regex, że nie jest wystarczająco restrykcyjne lub chciwy i faktycznie pasuje do całego pliku.

+0

teraz rodzaj słowy chcę tak są obecne w pliku type = "MAIL_ABC_CDE" type = "MAIL_XXX_AAA_AAA" itp może być dowolna liczba _ _ . Czy powinno być używanie reg exp i shoudl? Jakiś pomysł na ten temat? – AMM

5

Spróbuj następującą komendę

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

Od swoim komentarzu do odpowiedzi Thora wydaje chcemy także rozróżnić, czy tekst MAIL_.* jest węzłem tekstowym lub atrybutem, a nie tylko izolować go, gdy tylko pojawi się w dokumencie XML. Grep nie może parsować XML, you need a proper XML parser for that.

Parser xml wiersza poleceń to xmlstarlet. Jest pakowany w Ubuntu.

Używanie go na tym przykładzie np Plik:

$ 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> 

do wybierania węzłów tekstowych można użyć:

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

a dla atrybutów składzie:

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

krótkie wyjaśnienie:

  • //* jest wyrażenie XPath, które wybiera wszystkie elementy w dokumencie i text() wyprowadza wartość ich węzłów tekstowych dzieci, więc wszystko z wyjątkiem węzłów tekstowych zostaje przefiltrowany się
  • //*[@*] jest wyrażenie XPath, które wybiera wszystkie atrybuty w dokumencie i następnie @* wyprowadza ich wartość
Powiązane problemy