Unten ist der Text in der Datei:

Pseudo name=Apple Code=42B state=fault Pseudo name=Prance Code=43B state=good 

Ich muss nach suchen „42B“ und erhalten Sie die Ausgabe aus dem obigen Text wie folgt:

Pseudo name=Apple Code=42B state=fault 

Hat jemand eine Idee, wie dies mit grep / awk / sed?

Kommentare

  • Sie haben diese Frage nur mit " grep " markiert. Suchen Sie dann nur nach " grep " -Lösungen? In der Frage geben Sie auch awk & sed an. Können wir diese Tags hinzufügen? Ich war mir ' Ihrer Absicht nicht sicher, als ich die Frage letzte Nacht bearbeitet habe.
  • stackoverflow.com/ Fragen / 12024410 / …

Antwort

Mit awk

awk -v RS="" "/42B/" file 

RS= wird das Trennzeichen für Eingabedatensätze geändert von einer neuen Zeile zu leeren Zeilen. Wenn ein Feld in einem Datensatz /42B/ enthält, drucken Sie den Datensatz.

"" (die Nullzeichenfolge) ist eine Magie Wert zur Darstellung von Leerzeilen gemäß POSIX :

Wenn RS ist null, dann werden Datensätze durch Sequenzen getrennt, die aus einer <newline> plus einem oder mehreren Leerzeichen bestehen Zeilen, führende oder nachfolgende Leerzeilen dürfen zu Beginn oder am Ende der Eingabe nicht zu leeren Datensätzen führen, und ein <newline> muss immer ein Feldtrennzeichen sein, unabhängig vom Wert von FS ist.

Die ausgegebenen Absätze werden nicht getrennt werden, da das Ausgangstrennzeichen eine einzelne neue Zeile bleibt. Um sicherzustellen, dass zwischen den Ausgabeabsätzen eine Leerzeile steht, setzen Sie das Trennzeichen für den Ausgabedatensatz auf zwei neue Zeilen:

awk -v RS="" -v ORS="\n\n" "/42B/" file 

Kommentare

  • +1 für eine elegante Lösung. Sie müssen die Datei nicht ' umleiten, obwohl …
  • Finger auf Autopilot waren.
  • @jasonwryan, es sei denn, Sie benötigen Zugriff Für den Dateinamen in awk (FILENAME) ist es ' keine schlechte Idee, die Umleitung zu verwenden, da dies Probleme für Dateinamen mit = oder beginnend mit - (oder -) führt zu konsistenten Fehlermeldungen und Vermeidet das Ausführen von awk oder das Ausführen anderer Umleitungen, wenn die Eingabedatei ' nicht geöffnet werden kann.

Antwort

Angenommen, die Daten sind so strukturiert, dass es immer die Zeile davor und danach ist, können Sie die -A (nach) und -B (vor) wechselt, um anzugeben, dass die 1 Zeile vor dem Spiel und die 1 Zeile danach eingeschlossen werden sollen:

$ grep -A 1 -B 1 "42B" sample.txt Pseudo name=Apple Code=42B state=fault 

Wenn Sie das möchten Gleiche Zeilen vor und nach dem Suchbegriff können Sie den Schalter -C (Kontext) verwenden:

$ grep -C 1 "42B" sample.txt Pseudo name=Apple Code=42B state=fault 

If Wenn Sie beim Abgleichen der mehreren Zeilen strenger sein möchten, können Sie das Tool pcregrep verwenden, um a abzugleichen Muster über mehrere Zeilen:

$ pcregrep -M "Pseudo.*\n.*42B.*\nstate.*" sample.txt Pseudo name=Apple Code=42B state=fault 

Das obige Muster stimmt wie folgt überein:

  • -M – mehrere Zeilen
  • "Pseudo.*\n.*42B.*\nstate.*" – entspricht einer Gruppe von Zeichenfolgen, wobei die erste Zeichenfolge mit dem Wort "Pseudo" gefolgt von beliebigen Zeichen bis zum Ende der Zeile \n, gefolgt von beliebigen Zeichen bis zur Zeichenfolge "42B" gefolgt von beliebigen Zeichen bis ein weiteres Zeilenende (\n), gefolgt von der Zeichenfolge "state" gefolgt von beliebigen Zeichen.

Kommentare

  • -C (Kontext) kann als Verknüpfung verwendet werden, wenn -A und -B identisch sind.
  • @DavidBaggerman – danke. Fügte es der Antwort hinzu.
  • Warum die eine Abstimmung? Dies beantwortet die Frage.

Antwort

Die grep von Einige Unix-Varianten haben das Flag -p für „Absatz“. Ich weiß, dass AIX dies tut .

grep -p 42B <myfile> 

würde genau das tun, wonach Sie dort fragen YMMV und GNU grep haben dieses Flag nicht.

Kommentare

  • Es wäre wunderbar, das Flag -p zu haben. Insbesondere wenn es zusammen mit -v verwendet wird, können Sie ganze Absätze von der Ausgabe ausschließen.

Antwort

Es gibt wahrscheinlich einen ähnlich einfachen Weg, dies mit awk zu tun, aber in Perl:

cat file | perl -ne "BEGIN { $/="\n\n" }; print if $_ =~ /42B/;" 

Das bedeutet im Grunde, die Datei in durch Leerzeilen begrenzte Blöcke aufzuteilen und dann nur die Blöcke zu drucken, die Ihrem regulären Ausdruck entsprechen.

Kommentare

  • Dies kann vereinfacht werden, indem Optionen und Kurzzeichen verwendet werden und die nutzlose Verwendung von ; perl -00 -ne 'print if /42B/' file

Antwort

Eine andere Perl-Lösung ohne a Nachgestellte Leerzeile:

perl -00ne "if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}" foo 

Beispiel

% perl -00ne "if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}" foo Pseudo name=Apple Code=42B state=fault % cat foo Pseudo name=Apple Code=42B state=fault Pseudo name=Prance Code=43B state=good 

Kommentare

  • Oder kürzer (und damit besser lesbar), wie Triplee in einem Kommentar schrieb: perl -00 -ne 'print if /42B/' file.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.