У меня есть файл, который содержит строки как
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
Мне нужно извлечь значение прото которое tcp/http
, tcp/https
, udp/dns
.
До сих пор я пробовал это, grep -o 'proto=[^/]*/'
но только смог извлечь значение как proto=tcp/
.
sed
,awk
илиperl
, неgrep
.Ответы:
Предполагая, что это связано с вашим предыдущим вопросом , вы идете по неверному пути. Вместо того, чтобы пытаться собрать воедино кусочки скриптов, которые будут делать то, что вы хотите, большую часть времени, и вам нужно будет получать совершенно разные скрипты каждый раз, когда вам нужно будет сделать что-то хоть немного отличающееся, просто создайте 1 скрипт, который может анализировать ваши входной файл в массив (
f[]
ниже), который отображает ваши имена полей (теги) на их значения, а затем вы можете делать с результатом все, что захотите, например, учитывая этот входной файл из предыдущего вопроса:мы можем написать скрипт awk, который создает массив значений, проиндексированных по их именам / тегам:
и учитывая, что вы можете делать со своими данными все, что угодно, просто ссылаясь на них по именам полей, например, используя GNU awk
-e
для упрощения смешивания скрипта в файле со скриптом командной строки:источник
perl
может быть проще в использовании.awk
иsed
сценарии, как правило, проще,perl
потому что это по сути их расширенный набор, с дополнительными функциями для общих задач.s/old/new/g
sed и awk, поэтому давайте отложим это. Я совершенно не согласен с тем, что сложные сценарии awk проще в Perl. Конечно, они могут быть более краткими, но краткость не является желательным атрибутом программного обеспечения, лаконичность есть, и они очень редко получают какую-либо реальную выгоду, плюс их обычно намного труднее читать, поэтому люди публикуют такие вещи, как zoitz.com / archives / 13 о perl и относиться к нему как к языку только для записи, в отличие от awk. Я все еще хотел бы видеть Perl, эквивалентный этому, хотяС
grep -o
, вы должны будете точно соответствовать тому, что вы хотите извлечь. Поскольку вы не хотите извлекатьproto=
строку, вам не следует сопоставлять ее.Расширенное регулярное выражение, которое будет соответствовать
tcp
илиudp
после косой черты и некоторой непустой буквенно-цифровой строки:Применяя это к вашим данным:
Чтобы убедиться, что мы делаем это только в строках, начинающихся со строки
proto=
:С помощью
sed
удаления всего до первого=
и после первого пустого символа:Чтобы убедиться, что мы делаем это только для строк, начинающихся со строки
proto=
, вы можете вставить тот же шаг предварительной обработки,grep
как описано выше, или использоватьЗдесь мы подавляем вывод по умолчанию с помощью
-n
опции, а затем мы запускаем подстановки и явный вывод строки, только если строка совпадает^proto=
.Используя
awk
разделитель полей по умолчанию, а затем разделив первое поле=
и напечатав его второй бит:Чтобы убедиться, что мы делаем это только для строк, начинающихся со строки
proto=
, вы можете вставить тот же шаг предварительной обработки,grep
как описано выше, или использоватьисточник
Если вы используете GNU grep (для
-P
опции), вы можете использовать:Здесь мы сопоставляем
proto=
строку, чтобы убедиться, что мы извлекаем правильный столбец, но затем отбрасываем ее из вывода с\K
флагом.Выше предполагается, что столбцы разделены пробелом. Если табуляция также является допустимым разделителем, вы должны использовать
\S
для сопоставления непробельные символы, поэтому команда будет:Если вы также хотите защитить от полей соответствия, где
proto=
есть подстрока, напримерthisisnotaproto=tcp/https
, вы можете добавить границу слова\b
следующим образом:источник
grep -oP 'proto=\K\S+'
. За пробеломproto=tcp/http
может следовать табуляция вместо пробелов, и в\S
отличие от этого[^ ]
будет соответствовать любой непробельный символ.-o
это тоже GNUism.-P
поддерживается только GNU,grep
если он создан с поддержкой PCRE (необязательно во время сборки).Использование
awk
:$1 ~ "proto"
будет гарантировать, что мыproto
действуем только в строках с первым столбцомsub(/proto=/, "")
удалитproto=
из вводаprint $1
печатает оставшийся столбецисточник
Код игры в гольф на
grep
решенияхили даже
источник
Используя
cut
команду:источник
http
иdns
линиях.Просто еще одно
grep
решение:И аналогичный с
sed
печатью только сопоставленной захваченной группы:источник
Другой
awk
подход:Это установит в качестве разделителя полей awk либо
=
пробел, либо. Затем, если строка соответствует a=
, затем либо,ud
либоtc
после ap
, выведите 2-е поле.Другой
sed
подход (не переносимый на все версииsed
, но работает с GNUsed
):Значения
-n
«не печатать» и-E
включает расширенные регулярные выражения, которые дают нам\S
«непробельные символы»,+
«один или несколько» и круглые скобки для захвата. Наконец,/p
в конце команда sed будет печатать строку только в том случае, если операция была успешной, поэтому, если было найдено совпадение для оператора подстановки.И, perl один:
Это
-n
означает «читать входной файл построчно и применять скрипт, заданный-e
для каждой строки».-l
Добавляет символ новой строки к каждомуprint
вызову (и удаляет покидающих перевода строки из входного). Сам скрипт напечатает самый длинный отрезок непробельных символов, найденных после aproto=
.источник
-E
становится все более портативным, но\S
это не так.[^[:space:]]
это более переносимый эквивалент.Вот еще одно довольно простое решение:
источник
grep
ничего не соответствует.[tc,ud]\*\\/.*
выглядит для одного вхождения либоt
, илиc
, или ,,
или ,u
илиd
, а затем буквального*
характер, тоp
обратная косая черта. Вы, наверное, имели в видуgrep -Eo '(tc|ud)p/.* ' file | awk '{print $1}'
. Но, если вы используете AWK, вы можете также сделать все это в AWK:awk -F'[= ]' '/(tc|ud)p/{print $2}' file
.[tc,ud]p
означает «один изt
,c
,,
,u
илиd
сопровождаемыйp
. Так что это соответствует здесь только потому , чтоtcp
естьcp
иudp
естьdp
. Но это будет также соответствовать,p
или иtp
т.д. Кроме того , теперь, когда у вас есть*
, это будет соответствовать ,ppp
а также (*
означает «0 или более» , так что будет соответствовать , даже если он не соответствует) вы не хотите , класс символов (.[ ]
), что вы хотите , это группа:(tc|ud)
(использование с-E
флагомgrep
.) Кроме того ,.*
делает его соответствовать всей линии.\*
чтобы первые*
в их команде отображались как *, а не как курсивная уценка. Когда вы помещаете команду в кодовый формат, вы вызываете\
перед*
появлением (что приводит к сбою команды). Когда вы редактируете посты других людей, пожалуйста, следите за изменением внешнего вида поста, как это.ppp
. Конечно , вы правы , что это будет соответствовать,p
илиtp
- илиuucp
,ttp
,cutp
,ductp
илиd,up
.источник
варианты резки:
-f
- поле-d
- делиметристочник