Ответ 1
См. fooobar.com/questions/143931/... для ответа, который был дублирован здесь.
Сегодня я искал команду онлайн для печати следующих двух строк после шаблона, и я наткнулся на команду awk, которую я не могу понять.
$ /usr/xpg4/bin/awk '_&&_--;/PATTERN/{_=2}' input
Может кто-нибудь объяснить это?
См. fooobar.com/questions/143931/... для ответа, который был дублирован здесь.
_
используется здесь как имя переменной (действительный, но явно запутанный). Если вы перепишете его как:
awk 'x && x--; /PATTERN/ { x=2 }' input
тогда немного легче разобрать. Всякий раз, когда /PATTERN/
сопоставляется, переменная получает значение 2
(и эта строка не выводится) - это вторая половина. Первая часть срабатывает, когда x
не равна нулю и уменьшает x
, а также печатает текущую строку (действие по умолчанию, поскольку в этом предложении не указано действие).
Конечным результатом является печать двух строк сразу после любого совпадения шаблона, если ни одна из этих строк также не соответствует шаблону.
Проще говоря, команда выдает несколько строк после того, как соответствующее выражение регулярного выражения не совпадает с совпадающей строкой.
Количество строк указывается в блоке {_=2}
, а переменная _
равна 2, если строка соответствует PATTERN
. Каждая строка, считанная после соответствующей строки, приводит к уменьшению _
. Вы можете читать _&&_--
, как если бы _
больше нуля, а затем минус один, это происходит для каждой строки после совпадения, пока _
не достигнет нуля. Это довольно просто, если заменить переменную _
более разумным именем, например n
.
Простая демонстрация должна очистить (напечатайте две строки, которые соответствуют любой строке, соответствующей foo
):
$ cat file
foo
1
2
3
foo
a
b
c
$ awk 'n && n--;/foo/{n=2}' file
1
2
a
b
Итак, n
- только True, когда он получает значение 2 после сопоставления строки с foo
, а затем уменьшает n
и печатает текущую строку. Из-за awk
с оценкой короткого замыкания n
происходит только уменьшение, когда n
равно True (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
Дополнительно: тот факт, что используется полный путь к /usr/xpg4/bin/awk
, говорит, что этот код предназначен для машины Solaris, поскольку /usr/bin/awk
полностью сломан и его следует избегать любой ценой.
Чудесно неясно. Будет обновляться, если позволяет время.
_
используется как имя переменной. &&
является логическим оператором, который имеет 2 действительных действия, выполняемых вместе. Когда значение _ сводится к нулю, вторая половина && false, и никакой вывод не генерируется.
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
Объяснение
awk
выражения имеют следующий вид:
condition action; NEXT_EXPRESSION
Если conditon - это действительное действие (действия), будет выполнено. Обратите внимание, что если условие истинно, но действие было опущено awk
выполнит print
(действие по умолчанию).
У вас есть два выражения в коде, которые будут выполняться в каждой строке ввода:
_&&_-- ;
/PATTERN/{_=2}
Оба разделяются символом ;
. Поскольку я сказал, что действие по умолчанию print
произойдет, если действие опущено, оно совпадает с:
_&&_-- {print};
/PATTERN/ {_=2}
В вашем примере _
- это имя переменной, которое инициализируется 0
в первой строке ввода, перед первым использованием - автоматически с помощью awk.
Первое условие будет (0) && (0)
. Что приводит к тому, что условие является ложным, поскольку 0 && 0
оценивается как false
, а awk не будет печататься.
Если шаблон найден, _
будет установлен на 2
, что делает первое условие (2) && (2)
на следующей строке и (1) && (1)
на следующей строке после того, как эта строка как _
будет уменьшена после условие оценивается. Оба оценивают до true
, и awk будет печатать эти строки.
Однако, хорошая головоломка;)