BashとKornShell93の両方で機能させたいシェル関数のセットを書いていますが、Bashでは「循環名参照」の警告が表示されます。
これが問題の本質です。
_function set_it {
typeset -n var="$1"
var="hello:$var"
}
function call_it {
typeset -n var="$1"
set_it var
}
something="boff"
call_it something
echo "$something"
_
それを実行する:
_$ ksh script.sh
hello:boff
$ bash script.sh
script.sh: line 4: warning: var: circular name reference
hello:
_
KornShell93は私が望むことを正確に実行しますが、Bashは失敗し、スクリプト内のsomething
変数の名前がvar
の場合、2行目でも同じことを警告します。
var
変数を各関数に対してローカルにしたいので、typeset
を使用しますが、Bashは、nameref自体と同じ名前の変数にnamerefを「逆参照」することを好まないようです。 _local -n
_または_declare -n
_は、これらが不足しているksh
に割り込むため、使用できません。使用しても問題は解決しません。
私が見つけた唯一の解決策は、各関数で一意の変数名を使用することです。これはローカルであるため、かなりばかげているようです。
Bashのマニュアルには、typeset
について次のように書かれています。
typeset
[...]_
-n
_各名前にnameref
属性を付けて、別の変数への名前参照にします。その他の変数は、name
の値によって定義されます。 _-n
_属性自体の変更を除いて、name
へのすべての参照と割り当ては、nameの値によって参照される変数に対して実行されます。[...]
関数で使用する場合、_
-g
_オプションが指定されていない限り、declare
およびtypeset
は、local
コマンドと同様に、各名前をローカルにします。変数名の後に_=value
_が続く場合、変数の値はvalue
に設定されます。
Bashの名前参照と関数ローカル変数について私が理解していないことがあることは明らかです。
したがって、質問は次のとおりです。この場合、Bashの名前参照変数の処理について何かが足りないのでしょうか、それともこれはBashのバグ/誤機能ですか?
更新:現在、GNU bash, version 4.3.39(1)-release (x86_64-Apple-darwin15)
とGNU bash, version 4.3.46(1)-release (x86_64-unknown-openbsd6.0)
を使用しています。 macOSに同梱されているBashは古すぎて、名前の参照についてまったく知ることができません。
更新:さらに短い:
_function bug {
typeset -n var="$1"
printf "%s\n" "$var"
}
var="hello"
bug var
_
結果は_bash: warning: var: circular name reference
_になります。関数のvar
は、グローバルスコープのvar
とは異なるスコープを持つ必要があります。これにより、発信者に不要な制限が課せられます。 「この関数では(ローカル)namerefと名前が衝突する可能性があるため、変数に任意の名前を付けることはできません」という制限があります。
Chet Ramey(Bashメンテナ) 言う
今年の初めに、バグバッシュの名前参照について広範な議論がありました。この動作を変更する方法について合理的な提案があり、bash-4.4がリリースされた後に検討します。
その間、ローカルのnameref変数の名前を少し難読化して、ライブラリ内で衝突したり、(うまくいけば)グローバルなシェル変数名と衝突したりしないようにします。
bash
5.0では、これはわずかに修正されています(ただし、実際には修正されていません)。観察された動作は次のとおりです。
$ foo () { typeset -n var="$1"; echo "$var"; }
$ var=hello
$ foo var
bash: typeset: warning: var: circular name reference
bash: warning: var: circular name reference
bash: warning: var: circular name reference
hello
これは、それが機能することを示していますが、いくつかの警告もあります。
関連する [〜#〜] news [〜#〜] エントリは言う
i. A nameref name resolution loop in a function now resolves to a variable by that name in the global scope.