Grep Match und Extrahieren

Grep Match und Extrahieren

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 -omüssen Sie genau das abgleichen, was Sie extrahieren möchten. Da Sie die proto=Zeichenfolge nicht extrahieren möchten, sollten Sie sie nicht abgleichen.

tcpEin erweiterter regulärer Ausdruck, der entweder auf oder udpgefolgt 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 sedwird 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 grepoben einfügen oder verwenden

sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file

Hier unterdrücken wir die Standardausgabe mit der -nOption und lösen dann die Ersetzungen und einen expliziten Ausdruck der Zeile nur aus, wenn die Zeile übereinstimmt ^proto=.


Mit awkwird 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 grepoben einfügen oder verwenden

awk '/^proto=/ { split($1, a, "="); print a[2] }' file

Antwort2

Wenn Sie GNU grep verwenden (für die -POption), 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 \KFlag 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, \Sum 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 \bfolgt 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 protoin der ersten Spalte ausführen

sub(/proto=/, "")proto=wird aus der Eingabe entfernen

print $1druckt die verbleibende Spalte


$ awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
tcp/http
tcp/https
udp/dns

Antwort4

Nur eine andere grepLösung:

grep -o '[^=/]\+/[^ ]\+' file

Und ein ähnliches, bei dem sednur die übereinstimmende erfasste Gruppe gedruckt wird:

sed -n 's/.*=\([^/]\+\/[^ ]\+\).*/\1/p' file

verwandte Informationen