Три сдвига удаляют код ошибки, имя и строку из аргументов, поэтому остальные аргументы удобно находятся в $ @
для цикла for
в девятой строке скрипта. .
Я думаю, что вы упускаете то, что в настройке NR
getline
фактически использует линию. Таким образом, при втором вызове bar
уже отсутствует, а $0
равно baz
; 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.
Здесь должно быть ясно, что происходит следующее:
$0
с первой getline
tmp
с первой второй getline
tmp
, затем $0
, т.е. напечатайте строку 2, затем строку 1 При нечетном количестве строк последняя строка проходит через getline $0
, затем getline tmp
терпит неудачу, но вы не проверяете статус возврата, поэтому это просто оставляет tmp
без изменений, и в итоге вы снова печатаете предпоследнюю строку.