зависание awk при обращении к файлу

#unix #awk #command-line-interface

#unix #awk #интерфейс командной строки

Вопрос:

Поэтому, когда я запускаю это на mac:

 awk 'END { for (name in ENVIRON) {
  print "key: "name; }
}' >> app-deployment.yaml
  

awk просто зависает. Если я изменю его, чтобы просто печатать /dev/null , как это

 awk 'END { for (name in ENVIRON) {
  print "key: "name; }
}' < /dev/null
  

Все работает нормально. Я делаю что-то не так с моим перенаправлением? Есть ли что-то еще, что я здесь делаю неправильно?

Комментарии:

1. «чтение из» ( < ) ! = «запись в» ( >> ).

Ответ №1:

Измените END на BEGIN , чтобы иметь возможность работать без какого-либо ввода:

 awk 'BEGIN { for (name in ENVIRON) {
  print "key: "name; }
}' >> app-deployment.yaml
  

Ответ №2:

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

источник: стандарт POSIX awk

Итак, вкратце:

  • awk 'BEGIN{ action-without-getline }' : awk завершается без обработки каких-либо входных файлов
  • awk 'BEGIN{ action-with-getline }' : awk завершается после обработки входных файлов
  • awk 'END{ action }' : awk завершается после обработки входных файлов
  • awk 'BEGIN{action}END{ action }' : awk завершается после обработки входных файлов
  • awk 'BEGIN{action; exit}END{ action }' : awk завершается без обработки каких-либо входных файлов

Но что, если входные файлы не указаны:

Выполнение программы awk должно начинаться с первого выполнения действий, связанных со всеми BEGIN шаблонами, в том порядке, в котором они встречаются в программе. Затем каждый операнд файла (или стандартный ввод, если файлы не были указаны) должен обрабатываться по очереди…

источник: стандарт POSIX awk

Так что это просто означает, что

 $ awk 'END{action}'
  

не зависает, но ожидает ввода от /dev/stdin

Ответ №3:

Анализ кода OP 1:

 awk 'END { for (name in ENVIRON) {
  print "key: "name; }
}' >> app-deployment.yaml
  

Не имеет никакого Input_file, переданного awk и END блокируемого в любом awk коде, требует передачи любого Input_file, он зависает там, поскольку НЕ может его найти.



Анализ Code2 OP:

 awk 'END { for (name in ENVIRON) {
  print "key: "name; }
}' < /dev/null
  

Теперь вы передаете /dev/null в качестве входных данных awk (хотя у него НЕ будет никакого содержимого для чтения, awk но все же ему передается ввод), поэтому, согласно правилу, как только Input_file завершает обработку END блочных процессов, в данном случае, поскольку содержимого там нет, поэтому END должна произойти печать разделов операторов.

Чтобы заставить awk код работать без прохождения Input_file пути: на случай, если кто-то захочет awk работать без Input_file использования только BEGIN раздела, который, согласно man awk странице, будет выполнен до Input_file обработки, поэтому даже если вы НЕ передаете какой-либо Input_file, он НЕ будет ждать его присутствия, и как только BEGIN раздел будет выполнен, он выйдет из программы.