[解決済み] set -u` による Bash による空の配列展開
質問
bashスクリプトを書いているのですが、そのスクリプトには
set -u
で、空の配列の展開に問題があります。bash は展開中に空の配列を未設定の変数として扱うようです。
$ set -u
$ arr=()
$ echo "foo: '${arr[@]}'"
bash: arr[@]: unbound variable
(
declare -a arr
も役に立ちません)
これに対する一般的な解決策は
${arr[@]-}
を使うことで、("undefined") 空の配列の代わりに空の文字列を代入することです。しかし、これは良い解決策ではありません。なぜなら、1つの空の文字列を含む配列と空の配列の区別がつかなくなるからです。(bashでは@-expansionは特別で、これは
"${arr[@]}"
を
"${arr[0]}" "${arr[1]}" …
というように、コマンドラインを構築するための完璧なツールになります)。
$ countArgs() { echo $#; }
$ countArgs a b c
3
$ countArgs
0
$ countArgs ""
1
$ brr=("")
$ countArgs "${brr[@]}"
1
$ countArgs "${arr[@]-}"
1
$ countArgs "${arr[@]}"
bash: arr[@]: unbound variable
$ set +u
$ countArgs "${arr[@]}"
0
で配列の長さをチェックする以外に、この問題を回避する方法はあるのでしょうか?
if
で配列の長さをチェックする (下のコードサンプルを参照) か、あるいは
-u
をオフにするか?
if [ "${#arr[@]}" = 0 ]; then
veryLongCommandLine
else
veryLongCommandLine "${arr[@]}"
fi
更新しました。
削除された
bugs
タグを削除しました。
どのように解決するのですか?
この
のみ
安全なイディオムは
${arr[@]+"${arr[@]}"}
Bash 4.4+ にしか関心がないのであれば別ですが、もしそうであればこの質問を見ていないでしょう :)
これはすでに推奨されている
池上さんの回答
で推奨されていますが、このスレッドでは誤った情報や推測が多いですね。他のパターン、例えば
${arr[@]-}
とか
${arr[@]:0}
は
ではない
は、Bash のすべての主要なバージョンで安全ではありません。
下の表が示すように、すべての現代的なBashのバージョンで信頼できる唯一の拡張は
${arr[@]+"${arr[@]}"}
です (列
+"
). 注目すべきは、Bash 4.2では他のいくつかの展開が失敗し、(残念ながら)短い
${arr[@]:0}
イディオムもそうですが、これは単に間違った結果を出すだけでなく、実際に失敗します。
4.4 より前のバージョン、特に 4.2 をサポートする必要がある場合、このイディオムが唯一の動作するイディオムです。
残念ながら他の
+
の拡張は、一見すると同じように見えますが、実際には異なる振る舞いをします。使用する
:+
の代わりに
+
(
:+"
表中) は機能しません。
:
-展開
は、1つの空の要素を持つ配列 (
('')
) を "null" として扱い、したがって (一貫して) 同じ結果には展開されません。
ネストされた配列の代わりに完全な展開を引用する (
"${arr[@]+${arr[@]}}"
,
"+
のように)、ほぼ同等であると予想されますが、4.2でも同様に安全ではありません。
このデータを生成したコードと、いくつかの追加のバージョンの bash の結果は、次のサイトで見ることができます。 この gist .
関連
-
[解決済み] Bashスクリプトのソースディレクトリをスクリプト自体から取得するにはどうすればよいですか?
-
[解決済み] Bashシェルスクリプトでディレクトリが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashで通常のファイルが存在しないかどうかを判断する方法を教えてください。
-
[解決済み] Bashで文字列変数を連結する方法
-
[解決済み] Bashで文字列が部分文字列を含むかどうかをチェックする方法
-
[解決済み] Bash prints リテラルの改行をエコーする \n
-
[解決済み] Bashスクリプトからプログラムが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashで変数が設定されているかどうかを確認する方法は?
-
[解決済み] Bashで文字列の配列をループする?
-
[解決済み】Bashでファイル名と拡張子を抽出する。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Bashでユーザの入力を変数に読み込むには?
-
[解決済み] bash に次の行に進むように指示する方法
-
[解決済み] bashで変数に改行を埋め込もうとする [重複].
-
[解決済み] Git のコマンドライン・インターフェイスの言語を変更するにはどうしたらよいですか?
-
[解決済み] Bashでコマンド出力を隠す方法
-
[解決済み] Bashで$PATH変数からパスを削除する最もエレガントな方法は何ですか?
-
[解決済み] bashでalt + numericを押すと(arg [numeric])と出ますが、これは何でしょう?
-
[解決済み] Bashはどのように異なるディレクトリコンテキストでコマンドを実行できますか?
-
[解決済み] homebrew パッケージがインストールされているかどうかを検出する
-
[解決済み] MSYSでフォルダを閲覧する