私は初めてBashの補完を書くのに苦労しており、Bash配列を逆参照する2つの方法について少し混乱しています(${array[@]}
および${array[*]}
)。
関連するコードの塊は次のとおりです(ちなみに動作しますが、もっとよく理解したいと思います)。
_switch()
{
local cur perls
local ROOT=${PERLBREW_ROOT:-$HOME/Perl5/perlbrew}
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
perls=($ROOT/perls/Perl-*)
# remove all but the final part of the name
perls=(${perls[*]##*/})
COMPREPLY=( $( compgen -W "${perls[*]} /usr/bin/Perl" -- ${cur} ) )
}
Bashの ドキュメントによる :
配列の任意の要素は、$ {name [subscript]}を使用して参照できます。中括弧は、シェルのファイル名展開演算子との競合を避けるために必要です。添え字が「@」または「*」の場合、Wordは配列名のすべてのメンバーに展開されます。これらの添え字は、Wordが二重引用符で囲まれている場合にのみ異なります。 Wordが二重引用符で囲まれている場合、$ {name [*]}は各配列メンバーの値がIFS変数の最初の文字で区切られた単一のWordに展開され、$ {name [@]}はnameの各要素を展開します別のWordに。
今、私は_compgen -W
は、可能な選択肢のワードリストを含む文字列を想定していますが、このコンテキストでは、「$ {name [@]}がnameの各要素を個別のWordに展開する」という意味がわかりません。
長い話:${array[*]}
動作します。 ${array[@]}
しません。理由を知りたい、そして何を正確に理解したいのか_${array[@]}
に展開されます。
(これは、カレブ・ペダーソンの答えに対する私のコメントの拡張です-_[@]
_対_[*]
_のより一般的な扱いについては、その答えを参照してください。)
Bash(または同様のシェル)がコマンドラインを解析するとき、一連の「単語」に分割します(後で混乱を避けるために「シェル単語」と呼びます)。一般に、シェルワードはスペース(または他の空白)で区切られますが、スペースをエスケープまたは引用することでシェルワードに含めることができます。二重引用符で囲まれた_[@]
_と_[*]
_-拡張配列の違いは、_"${myarray[@]}"
_が配列の各要素を個別のシェルワードとして処理する一方で、_"${myarray[*]}"
_配列のすべての要素がスペース(またはIFS
の最初の文字が何であれ)で区切られた単一のシェルワードになります。
通常、_[@]
_の動作が必要です。 perls=(Perl-one Perl-two)
があり、_ls "${perls[*]}"
_を使用するとします。これは_ls "Perl-one Perl-two"
_と同等で、_Perl-one Perl-two
_という名前の単一のファイルを検索します。 _ls "${perls[@]}"
_は_ls "Perl-one" "Perl-two"
_と同等です。
compgen
に補完語(シェル語との混同を避けるためにcomp-wordと呼びます)のリストを提供することは異なります。 _-W
_オプションはコンプワードのリストを取りますが、コンプワードがスペースで区切られた単一のシェルワードの形式でなければなりません。 (少なくとも私の知る限り)常に引数を取るコマンドオプションは、単一のShell-Wordを取ることに注意してください。そうしないと、オプションへの引数が終了するタイミングと、通常のコマンド引数(/ otherオプションフラグ)開始。
さらに詳細に:
_perls=(Perl-one Perl-two)
compgen -W "${perls[*]} /usr/bin/Perl" -- ${cur}
_
以下と同等です:
_compgen -W "Perl-one Perl-two /usr/bin/Perl" -- ${cur}
_
...あなたが望むことをします。一方、
_perls=(Perl-one Perl-two)
compgen -W "${perls[@]} /usr/bin/Perl" -- ${cur}
_
以下と同等です:
_compgen -W "Perl-one" "Perl-two /usr/bin/Perl" -- ${cur}
_
...これは完全なナンセンスです。「Perl-one」は-Wフラグに接続された唯一のcomp-Wordであり、最初の実際の引数(compgenは文字列として完成する)は「Perl-two」です。/usr/bin/Perl」。 compgenは追加の引数( "-"および$ curにあるもの)が与えられていると文句を言うと思われますが、どうやらそれらは無視されるようです。