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
の場合、2行目でも同じことについて警告します。 スクリプト内の変数の名前はvar
代わりに。
var
が欲しいのですが 変数は各関数に対してローカルであるため、typeset
を使用します 、しかし、Bashは、nameref自体と同じ名前の変数にnamerefを「逆参照」することを好まないようです。 local -n
を使用できません またはdeclare -n
ksh
で壊れてしまうので これらが欠けていて、私がそうしたとしても、問題は解決しません。
私が見つけた唯一の解決策は、各関数で一意の変数名を使用することです。 、ローカルなのでかなりばかげているようです。
Bashのマニュアルには、typeset
について次のように書かれています。 :
typeset
[…]
-n
それぞれの名前にnameref
を付けます 属性、それを別の変数への名前参照
にします。その他の変数は、
name
の値によって定義されます。 。name
へのすべての参照と
割り当て 、-n
の変更を除く
属性自体は、名前の値によって参照される変数に対して実行されます。[…]
関数で使用する場合、
declare
およびtypeset
local
と同様に、各名前を
ローカルにします-g
でない限り、コマンド オプションが提供されます
。変数名の後に=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 "%sn" "$var"
}
var="hello"
bug var
結果はbash: warning: var: circular name reference
。 var
関数内で異なるスコープを持つ必要があります var
から グローバルスコープで。これにより、発信者に不要な制限が課せられます。制限は、「この関数では(ローカルの)namerefと名前が衝突する可能性があるため、変数に任意の名前を付けることはできません」です。
承認された回答:
チェット・ラミー(バッシュメンテナー)は言う
今年の初めに、バグバッシュのnamerefについて広範な議論がありました。
この動作を変更する方法について合理的な提案があります。
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.