
私は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