Gawk: 배열을 함수에 전달

Gawk: 배열을 함수에 전달

GNU awk 3.1.6을 고수하고 배열 버그가 수정되었다고 생각했지만 여전히 600줄 awk 프로그램에 범위 문제처럼 보이는 것이 있습니다. 내 오류를 찾으려면 awk의 배열 범위에 대한 이해를 확인해야 합니다.

이 예시적인 awk 코드가 주어지면 ...

function foo(ga) {
  ga[1] = "global result"
}

garray[1] = "global"
foo(garray)

print garray[1]

인쇄할 것이다...

global result

배열은 항상 참조로 함수에 전달되므로 모든 배열은 항상 전역 배열입니다. 로컬 배열을 생성할 수 없습니다. 맞습니까? 이를 명확하게 설명하는 문서를 찾을 수 없습니다.

나는 디버깅 중이고 3.1.6 자체에도 이 영역의 버그가 알려져 있으므로 awk의 오류가 어디서 시작되고 내 오류가 어디서 시작되는지 확인하려고 합니다.

추가됨: ga[]가 함수 내에서 작동하는 이유는 무엇입니까?

우선, 함수에 배열을 전달하는 것은 foo(ga)실제로 필요하지 않습니다. garray[]함수 내에서 액세스하면 됩니다 . 그러나 이렇게 하면 눈에 띄는 성능 저하가 발생하지 않으며 디버깅 및 오류 보고에 도움이 될 수 있습니다.

를 사용하는 경우 foo(ga)전역 ga[]배열과 동의어입니다 garray[]. 이는 의 로컬 복사본이 아니라 garray[]에 대한 포인터일 뿐입니다 garray[]. 심볼릭 링크가 파일에 대한 포인터인 것처럼 여러 이름을 사용하여 동일한 파일(또는 배열)에 액세스할 수 있습니다.

추가됨: Glenn Jackman의 답변에 대한 설명

배열을 생성할 때외부함수는 함수에 대해 전역적이며 함수에 전달되거나 참조될 수 있습니다. 배열이 생성됩니다.~에함수는 함수에 대해 로컬로 유지되며 함수 외부에는 표시되지 않습니다. Mr. Jackman의 예를 수정하면 이 점을 알 수 있습니다...

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: 
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: 

우리는 단지 x[]배열(실제로는 그에 대한 포인터)을 에 전달한다는 점에 유의하십시오 bar(). y[]배열은 함수를 입력하기 전에는 존재하지 않습니다.

하지만 함수 외부에서 아무것도 할당하지 않고 매개변수 목록 y[]에 포함하여 선언하면 호출 후에 표시됩니다...bar()bar(x,y)

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x,y)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: 
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: hello

마지막으로 y[]함수 외부에서 배열을 생성하여 에 전달하면 bar(x,y)함수 split()내부의 할당이 배열의 요소를 대체합니다.

awk '
    function bar(x,y) {
      split("hello world", y)
      print "x[1] inside: " x[1]
      print "y[1] inside: " y[1]
    }
    BEGIN {
      x[1]="goodbye"
      y[1]="howdy"
      print "x[1] before: " x[1]
      print "y[1] before: " y[1]
      bar(x,y)
      print "x[1] after: " x[1]
      print "y[1] after: " y[1]
    }
'
x[1] before: goodbye
y[1] before: howdy
x[1] inside: goodbye
y[1] inside: hello
x[1] after: goodbye
y[1] after: hello

답변1

함수 매개변수는 함수의 로컬 매개변수입니다.

awk '
    function foo(x,y) {y=x*x; print "y in function: "y} 
    BEGIN {foo(2); print "y out of function: " y}
'
y in function: 4
y out of function: 

인수보다 적은 수의 값이 함수에 전달되면 추가 인수는 비어 있게 됩니다. 때로는 다음과 같이 정의된 함수를 볼 수도 있습니다.

function foo(a, b, c            d, e, f) {...

공백 뒤의 매개 변수는 지역 변수이며 호출 시 값을 가져오도록 의도되지 않았습니다.

이것이 로컬 배열에서 작동하지 않을 이유가 없습니다.

awk '
    function bar(x) {
        split("hello world", x)
        print "in: " x[1]
    }
    BEGIN {
        x[1]="world"
        bar()
        print "out: " x[1]}
'
in: hello
out: world

답변2

이것멍청한 문서배열이 참조로 전달되는 것은 분명하며 이 문제를 해결할 수 있는 문서화된 방법은 없습니다. 동작은 4.0.1 과 동일합니다 gawk.

POSIX는 이 동작을 지정합니다awk, 따라서 다르게 동작하는 구현을 찾을 것으로 기대하지 않습니다 .

해당 기능이 필요한 경우 도구( ) 와 함께 제공되는 스크립트 를 perl.perla2pawkperl

관련 정보