Сегодня я искал команду онлайн для печати следующих двух строк после шаблона, и я наткнулся на команду awk, которую я не смог понять.Объясните команду awk
$ /usr/xpg4/bin/awk '_&&_--;/PATTERN/{_=2}' input
Может кто-нибудь объяснить это?
Сегодня я искал команду онлайн для печати следующих двух строк после шаблона, и я наткнулся на команду awk, которую я не смог понять.Объясните команду awk
$ /usr/xpg4/bin/awk '_&&_--;/PATTERN/{_=2}' input
Может кто-нибудь объяснить это?
Чудесно неясно. Будет обновляться, когда позволяет время.
_
используется как имя переменной. &&
является логическим оператором, который имеет 2 действительных действия, выполняемых вместе. После того, как значение _ сведено к нулю, вторая половина & & является ложной и никакой выход не генерируется.
print -- "
xxxxx
yyyy
PATTERN
zzz
aa
bbb
ccc
ddd" | awk '_&&_--;/PATTERN/{_=2}'
выход
zzz
aa
отладки версия
print -- "
xxxxx
yyyy
PATTERN
zzz
aa
bbb
ccc
ddd" | awk '_&&_--;{print "_="_;print _&&_};/PATTERN/{_=2;print "_="_ }'
выход
_=
0
_=
0
_=
0
_=
0
_=2
zzz
_=1
1
aa
_=0
0
_=0
0
_=0
0
_=0
0
Проще говоря, команда выдает несколько строк после того, как соответствующее выражение регулярных выражений совпадает с совпадающей строкой.
Число линий указано в блоке {_=2}
, а для переменной _
установлено значение 2, если линия соответствует PATTERN
. Каждая строка, прочитанная после соответствующей строки, приводит к уменьшению числа _
. Вы можете читать _&&_--
, как если бы _
больше нуля, а затем минус один из них, это происходит для каждой строки после матча, пока _
не достигнет нуля. Это довольно просто, когда вы заменяете переменную _
более разумным именем, например n
.
Простой демо должны четко (печать 2 строки, которые следуют за любую линию, соответствующую foo
):
$ cat file
foo
1
2
3
foo
a
b
c
$ awk 'n && n--;/foo/{n=2}' file
1
2
a
b
Так n
верно только, когда он получает значение 2 после согласования линии с foo
затем его уменьшается n
и печатает текущую строку. Благодаря awk
, имеющей оценку короткого замыкания n
только декремент, когда n
верно (п> 0) так что единственные возможные значения в этом случае для n
являются 2,1 или 0.
Awk имеет следующую структуру и condition{block}
когда условие оценивается True, тогда для текущей записи выполняется блок. Если вы не предоставляете блок awk
, то используется блок {print $0}
по умолчанию, поэтому n && n--;
- это условие без блока, которое оценивает только True для n
строк после соответствия регулярного выражения. Полуколона просто ограничивает условие n&&n--
для условий /foo/
, чтобы было ясно, что условие не имеет блока.
Для печати две строки ниже матч, включая матч вы могли бы сделать:
$ awk '/foo/{n=3} n && n--' file
foo
1
2
foo
a
b
Extra дополнительно: тот факт, что полный путь /usr/xpg4/bin/awk
используется говорит мне этот код предназначен для Solaris поскольку /usr/bin/awk
полностью сломан, и его следует избегать любой ценой.
_
здесь используется как переменное здесь (действительное, но явно запутанное). Если вы перепишите его как:
awk 'x && x--; /PATTERN/ { x=2 }' input
тогда немного легче разобрать. Всякий раз, когда сопоставляется /PATTERN/
, переменная получает значение 2
(и эта строка не выводится) - это вторая половина. Первая часть срабатывает, когда x
не равен нулю и уменьшает x
, а также печатает текущую строку (действие по умолчанию, так как в этом предложении не указано действие).
Конечный результат заключается в том, чтобы напечатать две строки сразу после любого соответствия шаблону, если ни одна из этих строк также не соответствует шаблону.
Объяснение
awk
выражения имеют следующий вид:
condition action; NEXT_EXPRESSION
Если Conditon верно действие (s) будет выполняться. Обратите внимание, что если условие истинно, но действие было опущено, awk
выполнит print
(действие по умолчанию).
У вас есть два выражения в вашем коде, которые будут выполнены на каждой строке ввода:
_&&_-- ;
/PATTERN/{_=2}
Оба разделенных ;
. Как я уже говорил, что действие по умолчанию print
произойдет, если действие опущено это же, как:
_&&_-- {print};
/PATTERN/ {_=2}
В вашем примере _
имя переменной, которая инициализируется с помощью 0
на первой строке ввода, до его первого использования - автоматически с помощью awk.
Первое условие будет (0) && (0)
.. Что приводит к тому, что условие является ложным, так как 0 && 0
оценивает до false
и awk не печатает.
Если шаблон найден, _
будет установлен в 2
, что делает первое условие будучи (2) && (2)
на следующей строке и (1) && (1)
на следующей строке после того, как линия _
уменьшается после того, как условие оценивается. Оба оценивают до true
, и awk напечатает эти строки.
Однако, хорошая головоломка;)
Небольшая ошибка, пост-декремент имеет более высокий порядок или приоритет, чем логический И так явно '(0) && (0 -)' as '(0 && 0) -' оценивается -1. –
приятно знать .. позвольте мне улучшить сообщение таким образом. – hek2mgl
@sudo_O 'awk '_ &&_--; 1 {printf"% i \ n ", _};/Pattern/{_ = 2}' input.txt' Я не понимаю вывод строки выше. Если декремент имеет место до (то, что соответствует awk docs, вы правы), тогда правая сторона '&&' должна быть 1 в первом тесте и 0 во втором тесте после соответствия шаблона. Поэтому я ожидаю, что будет напечатана только одна строка. Что мне здесь не хватает? – hek2mgl
См https://stackoverflow.com/a/17914105/1745001 ответ, который был дублирован здесь.
Очень хорошее объяснение – CBR