Intereting Posts
awk-код для умножения заданного столбца на число в файле, разделенном пространством не может прочитать ключ «net.ipv6.conf.all.stable_secret» в sysctl? Запустите fail2ban-regex, используя zcat Как добавить соответствующее количество 0 в числа, содержащиеся в именах изображений? Анализатор спектра звука Linux Где должны быть файлы конфигурации пользователя? Сценарий оболочки с трубами, не работающими в crontab Загрузочный загрузчик XEN Bootloader или Kernel не является исполняемым / не может найти ядро ​​при использовании XM create Почему мой Grub не инициализирован в ботинке? / home / amnesia / myfile: команда не найдена – 64-разрядный исполняемый файл, 64-битное ядро Строка состояния tmux, крайняя справа, несколько символов исчезают Как я могу установить мой .vimrc, какую ОС я использую? Запуск модулей ядра VirtualBox … не удалось Печать на Solaris Сценарий Bash для удаления каталогов старше 5 дней?

Разделитель между операторами в awk

Из руководства Gawk:

Если операторы awk в одном правиле короткие, вы можете поместить несколько строк в строку. Это достигается путем разделения операторов на точку с запятой (';'). Это также относится к самим правилам. Таким образом, программа, показанная в начале этого раздела, также может быть написана следующим образом:

/12/ { print $0 } ; /21/ { print $0 } 

ПРИМЕЧАНИЕ. Требование, указывающее, что правила на одной строке должно быть разделено точкой с запятой, не было в исходном языке awk; он был добавлен для согласованности с обработкой заявлений в рамках действия.

Но я видел из https://stackoverflow.com/q/20262869/156458

 awk '$2=="no"{$3="N/A"}1' file 

Не $2=="no"{$3="N/A"} и 1 два оператора? почему они ничем не отделены?

Благодарю.

Очень хороший вопрос! Я думаю, что ключ заключается в следующем: «Таким образом, программа, показанная в начале этого раздела, также может быть написана следующим образом:

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

 $ awk '/12/ { print $0 } /21/ { print $0 }' file $ awk '/12/ { print $0 } ; /21/ { print $0 }' file 

Я думаю, что использование этой точки с запятой должно охватывать действительно короткий идиоматический код, например, случаи, когда мы опускаем часть действия, и мы хотим применить несколько правил в одной строке:

 $ awk '/12//21/' file awk: cmd. line:2: /12//21/ awk: cmd. line:2: ^ unexpected newline or end of string 

В этом случае использование точки с запятой является обязательным для разделения правил (= условий):

 $ awk '/12/;/21/' file 

Поскольку часть {action} ограничена в обоих правилах / обоих условиях, действие по умолчанию будет выполняться для каждого правила = {print $0}

В gawk эти две цитаты из руководства описывают проблему:

Действие состоит из одного или нескольких операторов awk, заключенных в фигурные скобки ('{…}'). Каждое утверждение указывает на одну вещь. Операторы разделяются символами новой строки или точкой с запятой.

Точка с запятой – это « разделитель », но не « терминатор ».
Единственным действительным терминатором действия является закрывающая скобка ( } ).

Следовательно, то, что следует за закрывающей скобкой действия ( } ), должно быть каким-то другим шаблоном {действием}

В «man mawk » есть другое описание, которое может помочь прояснить, что должен делать awk:

Заявления заканчиваются символами новой строки, полуколонами или обоими. Группы операторов, таких как действия или тела цикла, блокируются с помощью {…}, как в C. Последнему оператору в блоке не нужен терминатор.

«Человек- нак » объясняет это так:

Сначала идет шаблон, а затем действие. Операторы действий заключены в {и}.

И, если вы хотите остановиться на деталях, прочитайте описание POSIX :

 action : '{' newline_opt '}' | '{' newline_opt terminated_statement_list '}' | '{' newline_opt unterminated_statement_list '}' ; 

Ищите список инструкций «unterminated».

Или, проще, искать действие для чтения:

Любой отдельный оператор может быть заменен списком операторов, заключенным в фигурные скобки. Приложение должно гарантировать, что операторы в списке инструкций разделяются символами или символами.

Опять же: are separated by <newline> or <semicolon> characters

Точка с запятой между условными блоками представляется необязательной; только точки с запятой между операторами внутри блоков кажутся обязательными:

 $ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" } /bar/ {print "bar found"}' foo found bar found $ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" }; /bar/ {print "bar found"}' foo found bar found $ echo -e "foo\nbar" | gawk '/foo/ { print "foo found"; print "whee" }' foo found whee $ echo -e "foo\nbar" | gawk '/foo/ { print "foo found" print "whee" }' gawk: cmd. line:1: /foo/ { print "foo found" print "whee" } gawk: cmd. line:1: ^ syntax error 

Однако, когда фактический кодовый блок между двумя условными обозначениями опущен в пользу значения по умолчанию (т.е. {print} ), точка с запятой становится необходимой:

 $ echo -e "foo\nbar" | gawk '/foo/ /bar/' gawk: cmd. line:2: /foo/ /bar/ gawk: cmd. line:2: ^ unexpected newline or end of string $ echo -e "foo\nbar" | gawk '/foo/; /bar/' foo bar