Wie zeige ich Linien nach jedem Grep-Match bis zu einem anderen bestimmten Match?

44

Ich weiß, dass ich mit dem "-A NUM"Schalter nach jeder Übereinstimmung eine bestimmte Anzahl von nachgestellten Zeilen drucken kann. Ich frage mich nur, ob es möglich ist, nachstehende Zeilen zu drucken, bis nach jedem Treffer ein bestimmtes Wort gefunden wird. zB Wenn ich nach "Word A" suche, möchte ich die Zeile mit "Word A" und die Zeilen danach bis zu der Zeile mit "Word D" sehen.

Kontext:

Word A
Word B
Word C
Word D
Word E
Word F

Befehl:

grep -A10 'Word A'

Ich brauche diese Ausgabe:

Word A
Word B
Word C
Word D
Meysam
quelle

Antworten:

73

Es scheint, dass Sie Zeilen zwischen ' Word A' und ' Word D' (einschließlich) drucken möchten . Ich schlage vor, Sie sedanstelle von zu verwenden grep. Hier können Sie eine Reihe von Eingabestreams bearbeiten, die mit den gewünschten Mustern beginnen und enden. Sie sollten nur anweisen sed, alle Zeilen im Bereich und keine anderen Zeilen zu drucken:

sed -n -e '/Word A/,/Word D/ p' file
saeedn
quelle
Irgendwelche Tipps, wie man es exklusiv macht (für jede allgemeine Situation, nicht nur für OPs)?
2. Februar,
4
@ 2rs2ts um es exklusiv zu machen, füge einfach hinzu | sed -e '1d;$d', das heißt entferne die erste und letzte Zeile
holroy
Und wenn Sie alle Zeilen zwischen ausschließen möchten - das heißt, Sie möchten nur die Zeilen sehen, die außerhalb der beiden Übereinstimmungen liegen -, dann: sed -n -e '/pattern A/,/pattern D/d; p'"Löschen Sie von Muster A zu Muster D und drucken Sie alles andere". Leider ist dieses Match gierig. Das heißt, wenn Muster A und D mehrmals auftreten, werden Sie vom ersten Muster A zum letzten Muster D passen . Ich fürchte, Perl oder Python sind Ihre Freunde, wenn das der Fall ist.
fbicknel
16

warum nicht awk benutzen?

awk '/Word A/,/Word D/' filename
cesar
quelle
2
sed scheint dies viel effizienter zu können, wenn eine große Anzahl von Dateien betroffen ist. awk ist vielleicht leichter zu merken, aber sed scheint eine Notiz in meinem Gehirn wert zu sein.
JimNim
1
awk ist überlegen, wenn es Word Dauf die gleiche Linie fällt wie Word A, und möglicherweise an einer anderen Stelle, z. B. wenn Word A Word D\nWord Dsed zwei Linien anzeigt, während awk eine anzeigt. Zusätzlich kann man mit awk noch Variablen verwenden, z. B. awk -v _word="Word A" '$0 ~ _word,/Word D/' "/some/file", so dass es vielleicht effizienter ist, aber wenn man sich mit der Suche nach zwei Zeichenketten befasst, die auf die gleiche Zeile fallen oder nicht, ist awk definitiv zuverlässiger.
S0AndS0
Es scheint, dass awk den Fall besser handhabt, dass die Datei Sequenzen von Aund enthält Bund Sie nur erfassen möchten, was zwischen diesen Sequenzen liegt. anscheinend folgt sed zumindest in meinem fall nicht dieser semantik.
Matan
9
perl -lne 'print if /Word A/ .. /Word D/' file

oder

cat file | perl -lne 'print if /Word A/ .. /Word D/'
vinian
quelle
1
+1, um der vorbeifahrenden Abwertung entgegenzuwirken. Ich würde immer noch dafür verwenden sed, es sei denn, Sie benötigen die Leistungsfähigkeit regulärer Perl-Ausdrücke, um die Begrenzungslinien auszuwählen.
Tripleee
Leute, die in den 70ern sed geschrieben haben, müssen dankbar sein :-)
Matan