~からhttps://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
パラメータ拡張の基本形式はです
${parameter}
。 ...引数の最初の文字が感嘆符(
!
)の場合、1段階の変数間接指定が導入されます。 Bash は、残りの引数で構成される変数値を変数名として使用します。次に、その変数を展開し、引数自体の値ではなく、残りの置換にその値を使用します。これを間接拡張といいます。以下に説明する拡張は例外です${!prefix}
。${!name[@]}
感嘆符は、間接的な関係を紹介するために開く中括弧の直後になければなりません。...
${!prefix*} ${!prefix@}
IFS特殊変数の最初の文字で区切られた名前は、プレフィックスで始まる変数名に展開されます。 「@」を使用して二重引用符内に拡張が発生すると、各変数名は別々の単語に展開されます。
${!name[@]} ${!name[*]}
nameが配列変数の場合、nameに割り当てられた配列インデックス(キー)のリストに展開されます。 name が配列でない場合は、name 設定時に 0 に拡張され、それ以外の場合は null に拡張されます。 「@」を使用して二重引用符内に拡張が行われると、各キーは別々の単語に展開されます。
あなたが引用した詩のいくつかの例を挙げることができますか?私は彼らが何を意味するのかわかりません。
答え1
私たちは以下を比較して差別化する必要があります。
"${Var}" # Plain variable
"${!Var}" # Indirect expansion
"${!Var@}" # Prefix expansion
"${!Var[@]}" # Array keys expansion
"${Var[@]}" # Plain array expansion
*
非常に似ていますが、微妙な違いがある拡張機能もあります。
間接的な
間接的な例:
$ varname=var_one
$ var_one=a-value
$ echo "${varname}"
var_one
$ echo "${!varname} and ${var_one}"
a-value and a-value
プレフィックス
プレフィックスの例:
$ head_one=foo
$ head_two=bar
$ printf '<%s> ' "${!head@}"
<head_one> <head_two>
$ printf '<%s> ' "${!head*}"
<head_one head_two>
変数は、デフォルトでは空白のIFSの最初の文字として互いに固定されています(Space Tab NewLineデフォルトではIFSと同様)。
一般的な配列
@
合計の小さな(しかし重要な)違いを示す配列の例(使用されていません!)*
:
$ Array[1]=This
$ Array[2]=is
$ Array[3]=a
$ Array[4]=simple
$ Array[5]=test.
$ printf '<%s> ' "${Array[@]}"
<This> <is> <a> <simple> <test.>
$ printf '<%s> ' "${Array[*]}"
<This is a simple test.>
IFSに対する同じコメントもここに適用されます。
私は(意図的に)配列のインデックス0を割り当てませんでした。
配列を割り当てるより簡単な方法は次のとおりです。
$ Array=( "" This is a simple test.)
しかし、ここではインデックス0を使用する必要があり、私はnull値(上記のunset値とは異なります)を使用しました。
配列リスト
この目的のために、単純なインデックス配列(数字を含む)はあまり興味深いものではありません。
$ Array=( "" A simple example of an array.)
$ printf '<%s> ' "${!Array[@]}"
<0> <1> <2> <3> <4> <5> <6>
$ printf '<%s> ' "${!Array[*]}"
<0 1 2 3 4 5 6>
しかし、連想配列を使用すると、状況がさらに面白くなります。
$ unset Array # erase any notion of variable array.
$ declare -A Array # make it associative
$ Array=([foo]=one [bar]=two [baz]=three) # give it values.
$ printf '<%s> ' "${Array[@]}"
<two> <three> <one> # List of values.
$ printf '<%s> ' "${!Array[@]}"
<bar> <baz> <foo> # List of keys
$ printf '<%s> ' "${Array[*]}"
<two three one> # One string of list of values.
$ printf '<%s> ' "${!Array[*]}"
<bar baz foo> # One string of list of keys.
割り当てられた順序と順序が異なりますのでご注意ください。
メモ:私が思いついたすべての使い方は引用または引用されておら"${!Array[@]}"
ず、${!Array[@]}
まったく${!Array[*]}
同じように動作し、同じ出力(Bashから)を提供します。
ただし、IFS 値に対するシェル分割の影響を受けます。醜く常に問題になる「パス名拡張」もあります。一般的にはあまり役に立ちません。または極度の注意を払って使用してください。
答え2
見てBinaryZebraの答え詳細な説明のために。 TLDP の次の引用は間違っていることが知られています。
オリジナル:
見ているhttp://tldp.org/LDP/Bash-Beginners-Guide/html/sect_03_04.html:
「PARAMETER」の最初の文字が感嘆符の場合、Bash は「PARAMETER」の残りの部分からなる変数の値を変数名として使用し、変数を拡張し、その値を残りの置換に使用します。 「PARAMETER」自体の値です。これを間接拡張といいます。
もちろん、あなたは直接パラメータ拡張に精通しています。上下のように最も単純な場合でも常に発生するからです。
franky ~> echo $SHELL /bin/bash
以下は間接拡張の例です。
franky ~> echo ${!N*} NNTPPORT NNTPSERVER NPX_PLUGIN_PATH
これはechoとは異なります
$N*
。
シェルでその効果を見ることができます。
例:
$ TEST=(test1 test2 test3)
$ echo ${!TEST*}
TEST
$ echo ${!TEST[@]}
0 1 2
$ echo ${TEST[@]}
test1 test2 test3
$ echo ${#TEST[@]}
4
${!TEST[@]}
${TEST[@]}
、および使用の違いに注意してください${#TEST[@]}
。