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

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

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

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

  • Извлечение текста с помощью sed не работает должным образом
  • Лишь оставлять самую длинную линию, когда первая колонка дублируется
  • awk переменная как регулярное выражение
  • Прокрутите список через awk
  • Получить строки с максимальными значениями в столбце с помощью awk, uniq и sort
  • Удалить каждую N-ю строку в оболочке
  •  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

  • Grep огромное количество шаблонов из огромного файла
  • Дублирование строковой переменной в awk
  • Единая команда для перемещения домена из локальных областей cPanel в файл remotedomains?
  • рекурсивный поиск шаблона, затем для каждого матча распечатывают конкретный номер строки SEQUENCE: номер файла и отсутствие содержимого файла
  • Как удалить все неупорядоченные строки из текстового файла?
  • Нужна помощь в определении переменной в awk
  • 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 неизменным, и вы снова печатаете следующую строку.

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