Ich habe eine Datei, die Zeilen enthält wie
proto=tcp/http sent=144 rcvd=52 spkt=3
proto=tcp/https sent=145 rcvd=52 spkt=3
proto=udp/dns sent=144 rcvd=52 spkt=3
Ich muss den Wert von Proto extrahieren, der tcp/http
, tcp/https
, ist udp/dns
.
Bisher habe ich dies versucht, grep -o 'proto=[^/]*/'
konnte den Wert aber nur als extrahieren proto=tcp/
.
Antwort1
Bei grep -o
müssen Sie genau das abgleichen, was Sie extrahieren möchten. Da Sie die proto=
Zeichenfolge nicht extrahieren möchten, sollten Sie sie nicht abgleichen.
tcp
Ein erweiterter regulärer Ausdruck, der entweder auf oder udp
gefolgt von einem Schrägstrich und einer nicht leeren alphanumerischen Zeichenfolge zutrifft , ist
(tcp|udp)/[[:alnum:]]+
So wenden Sie dies auf Ihre Daten an:
$ grep -E -o '(tcp|udp)/[[:alnum:]]+' file
tcp/http
tcp/https
udp/dns
Um sicherzustellen, dass wir dies nur für Zeilen tun, die mit der Zeichenfolge beginnen proto=
:
grep '^proto=' file | grep -E -o '(tcp|udp)/[[:alnum:]]+'
Mit sed
wird alles vor dem ersten =
und nach dem ersten Leerzeichen entfernt:
$ sed 's/^[^=]*=//; s/[[:blank:]].*//' file
tcp/http
tcp/https
udp/dns
Um sicherzustellen, dass wir dies nur für Zeilen tun, die mit der Zeichenfolge beginnen proto=
, können Sie denselben Vorverarbeitungsschritt wie grep
oben einfügen oder verwenden
sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file
Hier unterdrücken wir die Standardausgabe mit der -n
Option und lösen dann die Ersetzungen und einen expliziten Ausdruck der Zeile nur aus, wenn die Zeile übereinstimmt ^proto=
.
Mit awk
wird der Standard-Feldtrenner verwendet, das erste Feld wird aufgeteilt =
und der zweite Teil davon wird gedruckt:
$ awk '{ split($1, a, "="); print a[2] }' file
tcp/http
tcp/https
udp/dns
Um sicherzustellen, dass wir dies nur für Zeilen tun, die mit der Zeichenfolge beginnen proto=
, können Sie denselben Vorverarbeitungsschritt wie grep
oben einfügen oder verwenden
awk '/^proto=/ { split($1, a, "="); print a[2] }' file
Antwort2
Wenn Sie GNU grep verwenden (für die -P
Option), können Sie Folgendes verwenden:
$ grep -oP 'proto=\K[^ ]*' file
tcp/http
tcp/https
udp/dns
Hier gleichen wir die proto=
Zeichenfolge ab, um sicherzustellen, dass wir die richtige Spalte extrahieren, verwerfen sie dann aber mit dem \K
Flag aus der Ausgabe.
Das Obige geht davon aus, dass die Spalten durch Leerzeichen getrennt sind. Wenn Tabulatoren ebenfalls ein gültiges Trennzeichen sind, würden Sie diese verwenden, \S
um die Zeichen außer Leerzeichen abzugleichen. Der Befehl wäre also:
grep -oP 'proto=\K\S*' file
Wenn Sie auch vor übereinstimmenden Feldern schützen möchten, in denen proto=
eine Teilzeichenfolge (z. B. ein ) enthalten ist thisisnotaproto=tcp/https
, können Sie eine Wortgrenze wie \b
folgt hinzufügen:
grep -oP '\bproto=\K\S*' file
Antwort3
Verwendung von awk
:
awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
$1 ~ "proto"
stellt sicher, dass wir nur Aktionen für Zeilen proto
in der ersten Spalte ausführen
sub(/proto=/, "")
proto=
wird aus der Eingabe entfernen
print $1
druckt die verbleibende Spalte
$ awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
tcp/http
tcp/https
udp/dns
Antwort4
Nur eine andere grep
Lösung:
grep -o '[^=/]\+/[^ ]\+' file
Und ein ähnliches, bei dem sed
nur die übereinstimmende erfasste Gruppe gedruckt wird:
sed -n 's/.*=\([^/]\+\/[^ ]\+\).*/\1/p' file