スクリプトがあります:
#!/bin/bash
s='1 2, 3 4,'
s0="$(echo ${s//,/ }|tr -s ' ')"
echo "s0: $s0"
d="'${s0//+([[:space:]])/"' '"}'"
echo "d: $d"
このスクリプトを実行すると、出力は次のようになります。
$ ./test.sh
s0: 1 2 3 4
d: '1 2 3 4'
Bashプロンプトでコマンドを1つずつ実行すると、$d
変数が正しく表示されます。
$ s='1 2, 3 4,'
$ s0="$(echo ${s//,/ }|tr -s ' ')"
$ echo "s0: $s0"
s0: 1 2 3 4
$ d="'${s0//+([[:space:]])/"' '"}'"
$ echo "d: $d"
d: '1' '2' '3' '4'
$
コマンドはbashで実行されます。
$ type bash
bash is /bin/bash
$ echo $0
-bash
予想される代わりに$d
スクリプトの実行中に設定されるのはなぜですか?'1 2 3 4'
'1' '2' '3' '4'
答え1
Bashでは拡張グローブはデフォルトで有効になっていないため、スクリプトで明示的に有効にする+(...)
必要があります。shopt -s extglob
インタラクティブシェルがextglob
有効になっている可能性があるため(一部の起動ファイルで)、コマンドラインから置換コマンドを試すと、期待どおりに機能します。ただし、スクリプトではほとんどの起動ファイルが読み取られずにextglob
無効になり、プラス記号と角括弧はリテラル文字として扱われます。文字クラスは両方とも同じように動作するため、オフにすると+( )
同様のコンテンツがパターンと一致します。extglob
ここでパターンはどんなものとも一致せず、置換もなく、唯一の変更はd
拡張の周りに一重引用符が追加されることです${s0//...}
。