Объяснить команду awk

Сегодня я искал команду онлайн для печати следующих двух строк после шаблона, и я наткнулся на команду awk, которую я не могу понять.

$ /usr/xpg4/bin/awk '_&&_--;/PATTERN/{_=2}' input

Может кто-нибудь объяснить это?

Ответы

Ответ 2

_ используется здесь как имя переменной (действительный, но явно запутанный). Если вы перепишете его как:

awk 'x && x--; /PATTERN/ { x=2 }' input

тогда немного легче разобрать. Всякий раз, когда /PATTERN/ сопоставляется, переменная получает значение 2 (и эта строка не выводится) - это вторая половина. Первая часть срабатывает, когда x не равна нулю и уменьшает x, а также печатает текущую строку (действие по умолчанию, поскольку в этом предложении не указано действие).

Конечным результатом является печать двух строк сразу после любого совпадения шаблона, если ни одна из этих строк также не соответствует шаблону.

Ответ 3

Проще говоря, команда выдает несколько строк после того, как соответствующее выражение регулярного выражения не совпадает с совпадающей строкой.

Количество строк указывается в блоке {_=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 полностью сломан и его следует избегать любой ценой.

Ответ 4

Чудесно неясно. Будет обновляться, если позволяет время.

_ используется как имя переменной. && является логическим оператором, который имеет 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

Ответ 5

Объяснение

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 будет печатать эти строки.

Однако, хорошая головоломка;)