У меня есть файл, который содержит строки, как
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
Мне нужно извлечь значение proto, которое равно tcp/http
, tcp/https
, udp/dns
.
До сих пор я пробовал это сделать, grep -o 'proto=[^/]*/'
но смог извлечь значение только в виде proto=tcp/
.
решение1
С grep -o
, вам придется сопоставлять именно то, что вы хотите извлечь. Поскольку вы не хотите извлекать строку proto=
, вам не следует сопоставлять ее.
Расширенное регулярное выражение, которое будет соответствовать либо tcp
, либо , udp
за которым следует косая черта и некоторая непустая буквенно-цифровая строка:
(tcp|udp)/[[:alnum:]]+
Применяем это к вашим данным:
$ grep -E -o '(tcp|udp)/[[:alnum:]]+' file
tcp/http
tcp/https
udp/dns
Чтобы убедиться, что мы делаем это только для строк, начинающихся со строки proto=
:
grep '^proto=' file | grep -E -o '(tcp|udp)/[[:alnum:]]+'
С помощью sed
, удалив все до первого =
и после первого пробела:
$ sed 's/^[^=]*=//; s/[[:blank:]].*//' file
tcp/http
tcp/https
udp/dns
Чтобы убедиться, что мы делаем это только для строк, начинающихся со строки proto=
, вы можете вставить тот же шаг предварительной обработки, что grep
и выше, или вы можете использовать
sed -n '/^proto=/{ s/^[^=]*=//; s/[[:blank:]].*//; p; }' file
Здесь мы подавляем вывод по умолчанию с помощью -n
параметра, а затем запускаем подстановки и явную печать строки только в том случае, если строка соответствует ^proto=
.
С помощью awk
, используя разделитель полей по умолчанию, а затем разделив первое поле =
и выведя его вторую часть:
$ awk '{ split($1, a, "="); print a[2] }' file
tcp/http
tcp/https
udp/dns
Чтобы убедиться, что мы делаем это только для строк, начинающихся со строки proto=
, вы можете вставить тот же шаг предварительной обработки, что grep
и выше, или вы можете использовать
awk '/^proto=/ { split($1, a, "="); print a[2] }' file
решение2
Если вы используете GNU grep (для -P
опции), вы можете использовать:
$ grep -oP 'proto=\K[^ ]*' file
tcp/http
tcp/https
udp/dns
Здесь мы сопоставляем proto=
строку, чтобы убедиться, что извлекаем правильный столбец, но затем отбрасываем его из вывода с помощью флага \K
.
Вышеуказанное предполагает, что столбцы разделены пробелами. Если табуляция также является допустимым разделителем, вы должны использовать \S
для сопоставления непробельных символов, поэтому команда будет выглядеть так:
grep -oP 'proto=\K\S*' file
Если вы также хотите защитить поля совпадений, где proto=
есть подстрока, например thisisnotaproto=tcp/https
, , вы можете добавить границу слова \b
следующим образом:
grep -oP '\bproto=\K\S*' file
решение3
С использованием awk
:
awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
$1 ~ "proto"
гарантирует, что мы предпримем действия только по строкам proto
в первом столбце
sub(/proto=/, "")
удалит proto=
из ввода
print $1
печатает оставшийся столбец
$ awk '$1 ~ "proto" { sub(/proto=/, ""); print $1 }' input
tcp/http
tcp/https
udp/dns
решение4
Еще одно grep
решение:
grep -o '[^=/]\+/[^ ]\+' file
И аналогичный пример с sed
выводом только совпавшей захваченной группы:
sed -n 's/.*=\([^/]\+\/[^ ]\+\).*/\1/p' file