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
.perl
a2p
awk
perl