95

「初心者のためのバッシュガイド」を読んでいます。それは言う:

の最初の文字がPARAMETER感嘆符である場合、Bashは残りの部分から形成された変数の値を変数PARAMETERの名前として使用します。次に、この変数が展開され、その値は、それ自体の値ではなく、残りの置換で使用されPARAMETERます。これは、間接拡張として知られています。

与えられた例は次のとおりです。

franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH

私はここで完全に理解していません:

残りの部分から形成された変数の値PARAMETER

PARAMETERただのよう!N*に、

残りのPARAMETER

ただN*です。これはどのように変数を形成できますか?Bashはそこで可能なすべてのコマンドを検索しましたか?

4

6 に答える 6

122

マニュアルページを読むと、bash基本的にあなたが述べたことを確認します。

パラメーターの最初の文字が感嘆符(!)である場合、可変間接レベルのレベルが導入されます。Bashは、残りのパラメーターから形成された変数の値を変数の名前として使用します。次に、この変数が展開され、パラメーター自体の値ではなく、その値が残りの置換で使用されます。これは、間接拡張として知られています。

ただし、そこから読み進めてください。

これに対する例外は、以下の拡張${!prefix*}${!name[@]}説明です。

${!prefix*}プレフィックスに一致する名前。IFS名前が接頭辞で始まり、特殊変数の最初の文字で区切られた変数の名前に展開されます。

言い換えれば、あなたの特定の例${!N*}はあなたが引用した規則の例外です。ただし、次のような予想されるケースでアドバタイズされたとおりに機能します。

$ export xyzzy=plugh ; export plugh=cave

$ echo ${xyzzy}  # normal, xyzzy to plugh
plugh

$ echo ${!xyzzy} # indirection, xyzzy to plugh to cave
cave
于 2011-12-15T05:22:15.357 に答える
26

ここでのように、指定された「間接参照」がで終わる場合は例外のよう*です。この場合、指定した部分(Nここ)で始まるすべての変数名が付けられます。Bashは変数を追跡し、どの変数が存在するかを知っているため、これを実行できます。

真の間接参照は次のとおりです。
変数がに$VARIABLE設定され42ていて、別の変数$NAMEがに設定されているとしVARIABLEます。 ${!NAME}私に与えます42。ある変数の値を使用して、別の変数の名前を通知します。

$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42
于 2011-12-15T05:26:01.983 に答える
3

はい、!の後に変数の可能なすべての展開を検索します。行った場合:

echo ${!NP*}

あなただけを得るでしょうNPX_PLUGIN_PATH

次の例を考えてみましょう。

:~> export myVar="hi"
:~> echo ${!my*}
    myVar
:~> export ${!my*}="bye"
:~> echo $myVar
    bye
于 2011-12-15T05:20:52.773 に答える
3

間接処理で例外が発生しました。最後の文字がの場合、*前に指定されたプレフィックスを持つすべての変数が返されます。

于 2011-12-15T05:21:28.940 に答える
1

bashの間接参照および/またはnameref

この質問に遅れて来る、そして他の答えがnamerefについて教えていないので...

${!var} 間接構文の使用:

~$ someVariable='Some content'
~$ var=someVariable

~$ echo $var
someVariable

~$ echo ${!var}
Some content

namrefdeclare -n)構文の使用

namerefを使用すると、変数の内容を表示できるだけでなく、変数にデータを入力して属性を取得または設定できます。

~$ someVariable='Some content'
~$ declare -n var=someVariable
~$ echo $var
Some content

この構文は、関数に役立ちます。

function showVarDetail() {
    local -n var=$1
    printf 'Variable \47\44%s\47 is %d len, has [%s] flags and contain: %q\n' \
        "$1" "${#var}" "${var@a}" "$var"
}

(注:この関数は単なるサンプルです。これでは、配列連想配列が正しく展開されません!)

それで

~$ someVar='Hello world!'
~$ showVarDetail someVar
Variable '$someVar' is 12 len, has [] flags and contain: Hello\ world\!

~$ declare -r PI=3.14159265358979323844
~$ showVarDetail PI
Variable '$PI' is 22 len, has [r] flags and contain: 3.14159265358979323844

namerefを使用して変数値を設定する

これは両方の方法で機能する可能性があります!

これは、2つの変数名を引数として実行するための小さなサンプル関数です。最初の変数には文字列が含まれている必要があり、2番目の変数には1番目の変数コンテンツの1文字が入力され、次に1番目の変数コンテンツが1文字シフトされます。

shift1char <variable string source> <variable target>
shift1char () { 
    local -n srcStr=$1 tgtVar=$2;
    tgtVar=${srcStr::1} srcStr=${srcStr:1}
}

それで

~$ someVar='Hello world!'

~$ shift1char someVar someChar

~$ showVarDetail someVar
Variable '$someVar' is 11 len, has [] flags and contain: ello\ world\!

~$ showVarDetail someChar
Variable '$someChar' is 1 len, has [] flags and contain: H
于 2021-11-11T07:01:25.507 に答える
0

信頼できる情報については、bashについてこのGNUドキュメントを参照できます。

https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#Shell-Parameter-Expansion

ただし、基本的に、例外の1つとして間接展開は実行されません ${!prefix*} 。この例では、Nがプレフィックスです。

ドキュメントは、bashの間接的な拡張とは何かを説明します

于 2019-03-26T11:14:18.367 に答える