Как работает `getline` в AWK?

Я собрал пример, используя функцию AWK getline и это меня сбивает с толку.

 $ cat in foo bar baz $ awk '{ getline tmp; print tmp; print $0 }' in bar foo bar baz 

Я читаю следующую строку в переменной с именем tmp которая не меняет $0 что подтверждается двумя первыми строками вывода:

 bar foo 

Это подтверждается следующей таблицей, взятой на языке программирования AWK на стр. 62:

введите описание изображения здесь

Я знаю, что встроенные модули NR и FNR представляют собой количество строк, прочитанных до сих пор. Я думаю, что это ключ к пониманию того, что происходит, но я смущен тем, как изменение NR во время прохождения влияет на будущие проходы.

Я ожидал следующих двух строк:

 baz bar 

потому что на втором проходе $0 == bar и tmp == baz .

Тогда я ожидал, что следующие две строки действительно будут только одной строкой:

 baz 

потому что на третьем проходе $0 == baz и tmp == null .

Поэтому мой ожидаемый результат:

 bar foo baz bar baz 

Я думаю, что понимание того, как изменение NR во время цикла awk является ключом к пониманию этого результата.

  • Можете ли вы объяснить, почему мой ожидаемый результат неправильный и почему фактический результат прав?

Я запускаю awk version 20070501 на macOS 10.12.1

  • Использование cut / awk / sed с двумя разными разделителями
  • Лучший способ запустить серию из семи одинаковых команд в sed?
  • Обработка динамически изменяющихся позиций столбцов и разбиения файлов
  • grep first n и последние n символов из строки в файле
  • Полевая печать Awk в тернарном операторе
  • Получение подстрок между разделителями несколько раз из одной строки без цикла
  • Замена текста между двумя комментариями HTML
  • UNIX - команда разбивать файл на несколько файлов со всеми строками для каждых 3 уникальных значений в столбце
  • 2 Solutions collect form web for “Как работает `getline` в AWK?”

    Я думаю, что вам не хватает в том, что при настройке NR getline по сути потребляет линию. Таким образом, при втором вызове bar уже ушел, а $0baz ; getline пытается прочитать другую строку и не удается; и значение tmp остается неизменным (т.е. равным bar ).

    Это может быть проще понять, если вы проверите возвращаемое значение getline :

     awk '{ if ((getline tmp) > 0) print tmp; print $0 }' in bar foo baz 

    Должно быть ясно, если вы посмотрите на более крупную картину, так сказать. Программа awk представляет собой цикл вокруг текста программы, который читает одну строку, а затем выполняет программу в этой строке. Если вы читаете строку внутри программы, то окружающий цикл не видит эту строку: она уже потребляется.

    Например, ваша программа

     { getline tmp; print tmp; print $0 } 

    могут быть записаны как

     BEGIN { while (getline $0) { getline tmp; print tmp; print $0 } } 

    Блок BEGIN выполняется один раз в начале программы, и здесь программа ничего не делает – конечно, это очень неидиоматический способ написания awk-кода.

    Здесь должно быть ясно, что происходит:

    • Прочитайте строку 1 до $0 с первой getline
    • Прочитайте строку 2 в tmp со второй getline
    • Распечатайте tmp затем $0 , т.е. напечатайте строку 2, затем строку 1
    • Повторите со следующей парой строк: напечатайте линию 4, затем линию 3 и т. Д.

    С нечетным количеством строк последняя строка проходит через getline $0 , тогда getline tmp терпит неудачу, но вы не проверяете статус возврата, так что это просто оставляет tmp неизменным, и вы снова печатаете следующую строку.

    Interesting Posts

    Как исправить диакритические знаки в формах PDF в Evince?

    smartctl: приостановить чтение-проверку оставшейся части диска

    Обнуление / усечение десятичных знаков в столбце

    Распределение порядка стека каталога в zsh

    Разрешения Setfacl игнорируются для файла, скопированного по sftp

    Символы, отличные от ASCII, некорректно сохраненные при отправке почты в Emacs

    Создание программного обеспечения для Linux, созданного с использованием многострочной

    Принуждение GNU make для запуска команд в порядке

    Разрешить несколько удаленных подключений к пересылаемому порту ssh

    Создать список ошибок rsync – после факта

    Выполнение команд по нескольким файлам и предоставление каждому из них уникального имени

    Как узнать, какой модуль ядра поддерживает определенное оборудование

    OOM Killer – убил сервер MySQL

    расширить размер файловой системы reiserfs

    Выполняет ли Linux буферизацию дважды при размещении виртуальной машины?

    Linux и Unix - лучшая ОС в мире.