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
답변1
내 생각에 당신이 놓친 것은 설정 NR
에서 getline
실제로소비하다라인. 따라서 두 번째 호출에서는 가 bar
이미 사라지고 ; 다른 줄을 읽으려고 시도했지만 실패했습니다. 의 값은 변경되지 않고 그대로 유지됩니다(즉, 와 같음 ).$0
baz
getline
tmp
bar
다음의 반환 값을 확인하면 이해하기 더 쉬울 수 있습니다 getline
.
awk '{ if ((getline tmp) > 0) print tmp; print $0 }' in
bar
foo
baz
답변2
말하자면 더 큰 그림을 보면 명확해질 것입니다. awk 프로그램은 프로그램 텍스트 주위의 루프로, 한 줄을 읽은 다음 이 줄에서 프로그램을 실행합니다. 프로그램 내부에서 한 줄을 읽으면 주변 루프는 이 줄을 보지 못합니다. 이 줄은 이미 소비되었습니다.
예를 들어, 프로그램
{ getline tmp; print tmp; print $0 }
다음과 같이 쓸 수 있다
BEGIN {
while (getline $0) {
getline tmp; print tmp; print $0
}
}
블록 BEGIN
은 프로그램 시작 시 한 번 실행되며 여기서 프로그램은 다른 작업을 수행하지 않습니다. 물론 이는 awk 코드를 작성하는 매우 비관용적인 방법입니다.
여기서 일어나는 일은 다음과 같습니다.
$0
1행부터 첫 번째 행까지 읽기getline
tmp
2번째 줄부터 두 번째 줄 까지 읽어보세요getline
- Print
tmp
then$0
, 즉 2행을 인쇄한 다음 1행을 인쇄합니다. - 다음 줄 쌍으로 반복합니다. 4번 줄을 인쇄한 다음 3번 줄을 인쇄합니다.
홀수 줄의 경우 마지막 줄이 통과한 getline $0
다음 getline tmp
실패하지만 반환 상태를 확인하지 않으므로 tmp
변경되지 않은 상태로 유지되고 마지막에서 다음 줄을 다시 인쇄하게 됩니다.