НАЧИНАЙТЕ и КОНЕЦ с командой awk

13

Согласно руководству по awk, BEGIN и END используются не для согласования ввода, а для предоставления информации о запуске и очистке скрипта awk. Вот приведенный пример:

ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf

Сначала это печатает строку для вывода. Затем он проверяет ввод на совпадение с образцом, где ввод начинается с символа или, за которым следует любой символ, один или много раз, за ​​которым следует .conf. Для любых совпадений печатается 9-й столбец.

То, что мы вынуждены использовать, начинается здесь, означает ли это, что awk может использовать не более одной функции печати, содержащей BEGIN или END? Если нет, то почему мы не можем просто использовать функцию печати в начале без ключевого слова BEGIN? Кажется, НАЧАТЬ излишне.

JohnMerlino
источник
Простое выполнение команды без BEGIN ответит на ваш вопрос, показывая, что это не лишнее и что вы получите другой результат.
MSB

Ответы:

11

Это BEGINне лишнее. Если вы не укажете, BEGINто printбудет выполняться для каждой строки ввода.

Цитирование из руководства :

BEGINПравило выполняется только один раз, перед первым входом запись читается. Аналогично, ENDправило выполняется только один раз, после прочтения всего ввода.

$ seq 5 | awk 'BEGIN{print "Hello"}/4/{print}'   # Hello printed once
Hello
4
$ seq 5 | awk '{print "Hello"}/4/{print}'        # Hello printed for each line of input
Hello
Hello
Hello
Hello
4
Hello
$
devnull
источник
7

awkобрабатывает каждую строку ввода для выражений, заданных в теле, кроме BEGINи ENDблоков. В случае BEGINи ENDблоков, awkбудет обрабатывать заявления только один раз, прежде чем обработка ввода начала и после обработки ввода была сделана соответственно. Без BEGINблока не только вы не сможете печатать разовую информацию, такую ​​как заголовки, вы не сможете эффективно инициализировать некоторые переменные, необходимые для тела. Кроме того , FYI, awkпрограмма может иметь несколько BEGINи ENDблоки.

MKC
источник
2

awkвыполняет каждый блок только тогда, когда шаблон перед ним совпадает. Пустой шаблон (просто блок) соответствует каждой строке. BEGINи ENDявляются специальными шаблонами, которые соответствуют началу и концу файла (аналогично значению ^и $в горизонтальном направлении).

Если вы хотите что-то выполнить перед чтением файла, используйте BEGIN. Например, инициализация счетчиков или что-то. ENDмог тогда собрать результаты.

Орион
источник
0

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

1 == NR            { print "Files found:\n" }
/\<[a|x].*\.conf$/ { print $9               }

выдаст те же результаты, поскольку оператор print ограничен только первой строкой ввода.

Это , как говорится, BEGINи ENDблоки невероятно мощные инструменты. Как уже упоминалось в других решениях, вы можете использовать BEGINблок для инициализации переменных или других подпрограмм, которые необходимо выполнить только один раз, но его также можно использовать для запуска команд Awk, когда нет файлов для обработки. Простой пример:

BEGIN { print sqrt(12/4) }

Вы можете увидеть более серьезный пример программирования на Awk без какой-либо обработки здесь .

Аналогично, ENDблок чрезвычайно полезен для выполнения вычислений и суммирования всех входных данных. Это не может быть сделано (обычно) без предварительного чтения всех данных. Простой пример подведения итогов можно найти здесь

myq
источник