bashスクリプトは、bashプロンプトでコマンドを実行したときとは異なる出力を生成します。

bashスクリプトは、bashプロンプトでコマンドを実行したときとは異なる出力を生成します。

スクリプトがあります:

#!/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//...}

おすすめ記事