shopt -s nullglobが配列要素に疑問符を含む文字列を削除するのはなぜですか?

shopt -s nullglobが配列要素に疑問符を含む文字列を削除するのはなぜですか?

この小さな設定が私を狂わせます。

shopt -s nullglob

私はこれをbash 4.3スクリプトでグローバル設定として使用しています。空のディレクトリをスキャンするときのエラーの防止

これで理解できない奇妙な問題が見つかりました。

# shopt -s nullglob
# array=(foo bar)
# echo "${array[@]}"
foo bar
# array=(foo bar?)
# echo "${array[@]}"
foo
# shopt -u nullglob
# array=(foo bar)
# echo "${array[@]}"
foo bar
# array=(foo bar?)
# echo "${array[@]}"
foo bar?

ご覧のとおり、配列bar?要素から削除されました。ところで、なぜそうなのでしょうか?これ文書*とを含むことができるファイル名パターンを参照します?が、別の配列は「一致しないファイル」とは関係ありません。

If set, Bash allows filename patterns which match no files to expand to a null string, rather than themselves.

これはバグですか?

PS私の問題を解決するために、ループの周りにnullglobを設定/設定解除します。これは問題ではありません!

アップデート1

@MichaelHomerのリクエストに応じて:

# shopt -s nullglob
# array=(*)
# echo "${array[@]}"
1 Video_folder Server bin config dev etc etc.defaults initrd lib lib32 lib64 lost+found mnt proc root run sbin storage sys tmp tmpRoot usr var var.defaults volume1
# shopt -u nullglob
# array=(*)
# echo "${array[@]}"
1 Video_folder Server bin config dev etc etc.defaults initrd lib lib32 lib64 lost+found mnt proc root run sbin storage sys tmp tmpRoot usr var var.defaults volume1

これはどういう意味ですか?

ベストアンサー1

これにより、array=(foo bar?)文字列bar?は引用符ではなく、ファイル名のワイルドカード文字?(すべての単一文字と一致)が含まれます。これは、シェルがこの値に対してファイル名のグロービングを実行することを意味します。パターンが何も一致しない場合、デフォルトはそのままにしておくことです。一致するもの(たとえば、bar1など)がある場合は、bar-一致bar.する名前が配列に挿入されます。

有効にすると、一致するファイル名がないと、引用符のnullglobないglobbingパターンが完全に削除されます(通常、人々がアクティブにしたいのはこれです。)つまり、この場合、配列にはその要素のみが含まれます。bar?nullglobfoo

つまり、この設定は(現在のディレクトリのファイルを呼び出さない限りnullglob)引用符がない単語でも配列の要素として指定されることを防ぎます。bar?bar?

2つの文字列を配列にしたい場合はそれを引用することが解決策です(foo引用は必要ありませんが、一貫性を維持するのに問題はありません)。bar?foo

array=('foo' 'bar?')

この問題を「解決」する別の方法は次のとおりです。障害を負うファイル名ワイルドカード。これは以下を介して行われますset -f

set -f
array=(foo bar?)
set +f

おそらくMichaelが示したかったのは、array=(*)引用符のない値(ここでは引用符のない値*)のグロービングが発生することです。彼はこれが問題の源であるので、これを見せたいと思った。

おすすめ記事