Grep ist hierfür nicht geeignet, da sie in erster Linie für die Filterung bestimmte Zeilen, aber Sie fragen über die Beziehungen zwischen verschiedenen Linien. Grep kann gezwungen werden, einige Dinge über mehrere Zeilen hinweg durch (ab) mit der -z
Flag, die Nullbyte getrennte Zeilen erwartet, aber es ist in der Regel nicht schön.
Awk ermöglicht eine einfache Lösung:
$ awk 'BEGIN{RS="TAGDESCRIPTIONS"}/foo/{print $1}' infile
bar
Hier wird die Datensatztrennzeichen RS
zu TAGDESCRIPTIONS
, so wird die Eingabe als drei Datensätze (\n
steht für eine neue Zeile) interpretiert:
<empty record>
example\nTAGS tmp\nTAGS line\n
bar\nTAGS com\nTAGS foo\n
Die erste ist leer, da die Datei mit einem Datensatztrennzeichen beginnt.
Für jeden Datensatz haben wir bis zur ersten Zeilenumbruch die Tag-Beschreibung. Was wir mit
/foo/{print $1}
sagen ist: Wenn der Datensatz foo
entspricht, wobei das erste Feld des Datensatzes drucken (der Beschreibung).
Dies ist überhaupt nicht bombensicher. Wenn die Beschreibung aus mehreren Wörtern besteht, wird nur die erste ausgegeben. Wenn die Beschreibung anstelle des Tags übereinstimmt, handelt es sich um ein falsches positives Ergebnis. Wenn der Datensatz foobar
, aber nicht bar
enthält, wird er dennoch übereinstimmen.
Diese Eingabe Beispiel würde die einfache Lösung abwerfen:
TAGDESCRIPTIONS foo
TAGS blah
TAGDESCRIPTIONS example
TAGS tmp
TAGS line
TAGS foobar
TAGS barfoo
TAGDESCRIPTIONS bar and more words
TAGS com
TAGS foo
Es ist ein Tag Beschreibung mit foo
, Tags enthältfoo
und eine Tag-Beschreibung aus mehreren Wörtern bestehen.
Wir alle, dass bei Zeilenumbrüche durch Aufspalten der Aufzeichnungen beheben können, dann jedes Element außer der Beschreibung zum Suchbegriff Vergleich:
awk '
BEGIN { RS = "TAGDESCRIPTIONS *" }
{
# Split record at newlines, store in arr
split($0, arr, "\n")
# Skip first element (description), compare to 'foo'
for (i = 2; i <= length(arr); ++i) {
if (arr[i] ~ " +foo$") {
# Matches - print description
print arr[1]
# No need to look at the rest of the record
break
}
}
}' infile
was
bar and more words
GNU awk, um genau zu sein, aufgrund der Multi-Zeichen-Record-Trennzeichen und der length
-Funktion.
Sie sollten erwähnen, das ist gawk-spezifisch wegen Multi-Char RS und 'Länge (Array)'. –