it-swarm.com.de

Drucken Sie mit sed oder awk eine Zeile nach einem passenden Muster

Ich möchte eine einzelne Zeile direkt nach einer Zeile drucken, die ein übereinstimmendes Muster enthält. Meine Version von sed verwendet nicht die folgende Syntax (sie bombardiert +1p.), Was wie eine einfache Lösung erscheint:

sed -n '/ABC/,+1p' infile

Ich gehe davon aus, dass awk besser für mehrzeilige Verarbeitung geeignet ist, aber ich bin mir nicht sicher, wie sie es tun soll.

47
user1537723

Verwenden Sie niemals das Wort "Muster", da es sehr vieldeutig ist. Verwenden Sie immer "string" oder "regexp" (oder in Shell "globbing pattern"), je nachdem, was Sie wirklich meinen.

Die spezifische Antwort, die Sie wünschen, ist:

awk 'f{print;f=0} /regexp/{f=1}' file

oder Spezialisierung der allgemeineren Lösung des N-ten Datensatzes nach einem Regexp (Idiom "c" unten):

awk 'c&&!--c; /regexp/{c=1}' file

Die folgenden Ausdrücke beschreiben, wie ein Datensatzbereich ausgewählt wird, wenn ein bestimmter regulärer Ausdruck übereinstimmt:

a) Alle Datensätze eines regulären Ausdrucks ausgeben:

awk '/regexp/{f=1}f' file

b) Drucke alle Datensätze nach einem regulären Ausdruck:

awk 'f;/regexp/{f=1}' file

c) Drucken Sie den N-ten Datensatz nach einem regulären Ausdruck:

awk 'c&&!--c;/regexp/{c=N}' file

d) Drucken Sie jeden Datensatz mit Ausnahme des N-ten Datensatzes nach einem regulären Ausdruck:

awk 'c&&!--c{next}/regexp/{c=N}1' file

e) Drucken Sie die N-Datensätze nach einer gewissen Verlängerung:

awk 'c&&c--;/regexp/{c=N}' file

f) Drucke alle Datensätze mit Ausnahme der N-Datensätze nach einem regulären Ausdruck:

awk 'c&&c--{next}/regexp/{c=N}1' file

g) Drucken Sie die N-Datensätze von einem regulären Ausdruck aus:

awk '/regexp/{c=N}c&&c--' file

Ich habe den Variablennamen von "f" für "found" in "c" für "count" geändert, wobei Angemessen ist.

112
Ed Morton

Es ist die Linie after, die Sie interessiert, oder? In sed könnte das wie folgt erreicht werden:

sed -n '/ABC/{n;p}' infile

Alternativ können Sie auch die Option A von grep suchen.

-A NUM, Print NUM lines of trailing context after matching lines.

Zum Beispiel die folgende Eingabedatei:

foo
bar
baz
bash
bongo

Sie könnten Folgendes verwenden:

$ grep -A 1 "bar" file
bar
baz
$ sed -n '/bar/{n;p}' file
baz

Hoffentlich hilft das.

32
chooban

Ich musste ALLE Zeilen nach dem Muster drucken (ok Ed, REGEX), also entschied ich mich für dieses:

sed -n '/pattern/,$p' # prints all lines after ( and including ) the pattern

Aber da wollte ich alle Zeilen NACHS drucken (und das Muster ausschließen) 

sed -n '/pattern/,$p' | tail -n+2  # all lines after first occurrence of pattern

Ich denke, in Ihrem Fall können Sie am Ende einen head -1 hinzufügen

sed -n '/pattern/,$p' | tail -n+2 | head -1 # prints line after pattern
3
Mark

awk Version:

awk '/regexp/ { getline; print $0; }' filetosearch
2
tue

Wenn das Muster übereinstimmt, kopieren Sie die nächste Zeile in den Musterpuffer, löschen Sie eine Rückgabe und drucken Sie dann den quit - side Effekt.

sed '/pattern/ { N; s/.*\n//; q }; d'
1
Michael Back

Tatsächlich schlägt sed -n '/pattern/{n;p}' filename fehl, wenn die pattern -Zeilen mit continuous übereinstimmen:

$ seq 15 |sed -n '/1/{n;p}'
2
11
13
15

Die erwarteten Antworten sollten sein:

2
11
12
13
14
15

Meine Lösung lautet:

$ sed -n -r 'x;/_/{x;p;x};x;/pattern/!s/.*//;/pattern/s/.*/_/;h' filename

Zum Beispiel:

$ seq 15 |sed -n -r 'x;/_/{x;p;x};x;/1/!s/.*//;/1/s/.*/_/;h'
2
11
12
13
14
15

Erklärt:

  1. x;: Verwenden Sie am Anfang jeder Zeile der Eingabe den Befehl x, um den Inhalt in pattern space & hold space auszutauschen.
  2. /_/{x;p;x};: Wenn pattern space, das ist der hold space, tatsächlich _ enthält (dies ist nur eine indicator Anzeige) Wenn die letzte Zeile mit pattern übereinstimmt oder nicht), verwenden Sie x, um den tatsächlichen Inhalt von current line gegen pattern space auszutauschen. Verwenden Sie p zum Drucken von current line und x zum Wiederherstellen dieser Operation.
  3. x: Stellt den Inhalt in pattern space und hold space wieder her.
  4. /pattern/!s/.*//: Wenn current line NICHT mit pattern übereinstimmt, was bedeutet, dass die nächste folgende Zeile NICHT gedruckt werden soll, verwenden Sie den Befehl s/.*// zum Löschen Alle Inhalte in pattern space.
  5. /pattern/s/.*/_/: Wenn current line mit pattern übereinstimmt, was bedeutet, dass die nächste folgende Zeile gedruckt werden soll, müssen wir ein indicator setzen, um dies mitzuteilen sed, um die NÄCHSTE Zeile zu drucken. Verwenden Sie also s/.*/_/, um den gesamten Inhalt in pattern space durch einen _ zu ersetzen (der zweite Befehl verwendet ihn für beurteilen, ob die letzte Zeile mit dem pattern übereinstimmt oder nicht).
  6. h: überschreibt den hold space mit dem Inhalt in pattern space; dann ist der Inhalt in hold space^_$, was bedeutet, dass current line mit pattern übereinstimmt, oder ^$, was bedeutet current line stimmt NICHT mit pattern überein.
  7. der fünfte Schritt und der sechste Schritt können NICHT ausgetauscht werden, da nach s/.*/_/ der pattern space NICHT mit /pattern/ übereinstimmen kann, daher MUSS der s/.*// sein hingerichtet!
1
Weike

Das könnte für Sie funktionieren (GNU sed):

sed -n ':a;/regexp/{n;h;p;x;ba}' file

Verwenden Sie die seds-grep-ähnliche Option -n. Wenn die aktuelle Zeile den erforderlichen regulären Ausdruck enthält, ersetzen Sie die aktuelle Zeile durch die nächste. Kopieren Sie diese Zeile in den Speicherplatz (HS), drucken Sie die Zeile, tauschen Sie den Musterbereich (PS) für HS und aus wiederholen.

0
potong