AWK에서 `getline`은 어떻게 작동하나요?

AWK에서 `getline`은 어떻게 작동하나요?

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 == baztmp == null.

그래서 내 예상 결과는 다음과 같습니다.

bar
foo
baz
bar
baz

나는 NRawk 루프에서 어떻게 변화하는지 이해하는 것이 이 출력을 이해하는 열쇠라고 생각합니다.

  • 내 예상 출력이 잘못된 이유를 설명할 수 있습니까?그리고실제 출력이 올바른 이유는 무엇입니까?

난 달려가고 awk version 20070501있어macOS 10.12.1

답변1

내 생각에 당신이 놓친 것은 설정 NR에서 getline실제로소비하다라인. 따라서 두 번째 호출에서는 가 bar이미 사라지고 ; 다른 줄을 읽으려고 시도했지만 실패했습니다. 의 값은 변경되지 않고 그대로 유지됩니다(즉, 와 같음 ).$0bazgetlinetmpbar

다음의 반환 값을 확인하면 이해하기 더 쉬울 수 있습니다 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 코드를 작성하는 매우 비관용적인 방법입니다.

여기서 일어나는 일은 다음과 같습니다.

  • $01행부터 첫 번째 행까지 읽기getline
  • tmp2번째 줄부터 두 번째 줄 까지 읽어보세요getline
  • Print tmpthen $0, 즉 2행을 인쇄한 다음 1행을 인쇄합니다.
  • 다음 줄 쌍으로 반복합니다. 4번 줄을 인쇄한 다음 3번 줄을 인쇄합니다.

홀수 줄의 경우 마지막 줄이 통과한 getline $0다음 getline tmp실패하지만 반환 상태를 확인하지 않으므로 tmp변경되지 않은 상태로 유지되고 마지막에서 다음 줄을 다시 인쇄하게 됩니다.

관련 정보