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

Три сдвига удаляют код ошибки, имя и строку из аргументов, поэтому остальные аргументы удобно находятся в $ @ для цикла for в девятой строке скрипта. .

1
26.05.2017, 22:14
2 ответа

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

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

awk '{ if ((getline tmp) > 0) print tmp; print $0 }' in
bar
foo
baz
2
27.01.2020, 23:24

Это должно стать ясным, если вы, так сказать, посмотрите на картину в целом. Программа 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 без изменений, и в итоге вы снова печатаете предпоследнюю строку.

1
27.01.2020, 23:24

Теги

Похожие вопросы