2010-08-06 8 views
9

Ich gruppiere grundsätzlich mit einem regulären Ausdruck auf. In der Ausgabe möchte ich nur die Strings sehen, die zu meinem reg exp passen.In Grep auf Ubuntu, wie kann ich nur die Zeichenfolge anzeigen, die dem regulären Ausdruck entspricht?

In einer Reihe von XML-Dateien (meist sind es Einzeilendateien mit riesigen Datenmengen in einer Zeile), möchte ich alle Wörter erhalten, die mit MAIL_ beginnen.

Auch möchte ich den Grep-Befehl auf der Shell geben nur die Wörter, die übereinstimmten und nicht die gesamte Zeile (die in diesem Fall die gesamte Datei ist).

Wie mache ich das?

Ich habe

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

Antwort

13

Zuerst, mit GNU Grep, das mit Ubuntu installiert wird, ist -G Flag (verwenden Sie grundlegende Regexp) ist der Standard, so dass Sie es weglassen können, aber, noch besser, verwenden erweiterte Regexp mit -E.

-r Flag bedeutet rekursive Suche in Dateien eines Verzeichnisses, das ist, was Sie brauchen.

Und Sie haben das Recht, die Option -o zu verwenden, um einen übereinstimmenden Teil einer Zeile zu drucken. Um Dateinamen zu vermeiden, benötigen Sie die Option -h.

Der einzige Fehler, den Sie gemacht haben, ist der reguläre Ausdruck selbst. Sie haben die Zeichenspezifikation vor * verpasst. Ihr Befehl sollte wie folgt aussehen:

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

Beispielausgabe (nicht rekursiv):

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

great..that funktioniert, aber eine schnelle Frage Wie mache ich, wenn ich weiß, die MAIL_ * Sachen sind entweder als type = "MAIL_ *" oder> MAIL _ * AMM

+0

Ich verstehe es nicht. Könnten Sie Ihre Frage anders formulieren? Sie möchten umgebende Zeichen um Ihre MAIL_XXX Sachen sehen? Möchten Sie "und <> in der Ausgabe des Befehls grep sehen? – thor

+0

Wenn Ihr MAIL_ * nur alphabetische Zeichen (a-z) enthalten könnte, können Sie regexp in 'MAIL _ [[: alpha:]] * ändern.' – thor

2
grep -o or --only-matching 

man nur noch den passenden Text anstelle von kompletten Linien, aber das Problem könnte Ihre regex sein, die nicht als Einschränkung oder gierig genug und passt eigentlich die ganze Datei.

+0

jetzt die Art der Worte i sind, wie dies in der Datei vorhanden wollen type = "MAIL_ABC_CDE" type = "MAIL_XXX_AAA_AAA" etc es kann eine beliebige Anzahl von _ WHat sollte die reg exp sein, die ich benutze? Irgendeine Idee dazu? – AMM

5

Versuchen Sie den folgenden Befehl

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

Von Ihrem Kommentar zu Thor Antwort es scheint, dass Sie auch wollen um zu unterscheiden, ob der Text MAIL_.* ein Textknoten oder ein Attribut ist, nicht nur um ihn zu isolieren, wenn er im XML-Dokument erscheint. Grep kann XML, you need a proper XML parser for that nicht analysieren.

Ein Befehlszeilen-XML-Parser ist xmlstarlet. Es ist in Ubuntu verpackt.

es auf dieser Beispieldatei Beispieldatei verwenden:

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

Zur Auswahl Textknoten können Sie:

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

Und für die Auswahl von Attributen:

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

Kurze Erklärungen:

  • //* ist ein XPath-Ausdruck, der alle Elemente in dem Dokument auswählt und text() gibt den Wert ihrer Kinder Textknoten, steigt aus daher alles außer Textknoten gefiltert
  • //*[@*] ist ein XPath-Ausdruck, der alle Attribute in dem Dokument auswählt und gibt dann @* ihren Wert
Verwandte Themen