sh, bash, csh, zshのようなシェルでは
echo *.sh
などというように、ワイルドカードでファイル一覧を取得することができます。
シェルで使えるワイルドカードはアスタリスク(*)、クエスチョンマーク(?)の2種類で、それぞれ、0文字以上の任意の文字列、1文字の任意の文字(英数記号など)を表します。
ワイルドカード文字を、ワイルドカードとしてではなくただの * や ? という1つの文字として扱いたい場合は、次のようにクオート記号で囲むか、エスケープします。
echo "*.sh" echo "What's up?" # 結果 # *.sh # What's up? # が表示される
ここに変数が関係してくると、少し厄介なことになります。
# 間違った例 foo="SELECT * FROM table" echo $foo
この結果は、
SELECT * FROM table
と表示されるかと思いきや、アスタリスクがワイルドカードとして展開されてしまうため、
SELECT FROM table
とアスタリスクが消える、または、現在の作業フォルダのファイル一覧が展開されて、
SELECT bin boot home root var FROM table
のように意図しない結果になってしまいます。
これはかなり怖いことで、この動きにより、最悪致命的なセキュリティホールや、データ消失につながる場合があります。
これを回避するためには, ワイルドカード文字を含む変数の参照時は常にダブルクオート/シングルクオートの中で参照するというテクニックを使います。
# 正しい例 foo="SELECT * FROM table" echo "$foo"
この結果は、期待通り
SELECT * FROM table
となります。
多段になってもこの動きは変わりません。
foo="SELECT * FROM table" boo="$foo" echo "$boo" # foo, boo 両方の参照をダブルクォートでくくっていることに注意
この結果も、期待通り
SELECT * FROM table
となります。ここで
echo $boo
としていると、やはり変数展開されてしまうため、注意しましょう。
お約束として、変数を参照するときで、変数に記号が入る可能性がある場合は必ずダブルクオートで囲む癖をつけると、こういう間違いがなくなるので幸せになれます。
おまけ
一歩踏み込んだ例として、変数の遅延展開の例を紹介します。
export table=book # 1 # ↑これは全く利用されない text='SELECT * FROM ${table}' # 2 # ↑シングルクオートなので、textに入る時点ではtableが展開されない。 export table=member # 3 # ↑これが利用される。子プロセスで参照できるよう export している query=$(sh -c "echo \"$text\"") #4 # ↑ここでtableの中身が展開されます。* の展開を防ぐため $text をダブルクォートで囲んでいることに注意 echo "$query" # 5
この結果は、
SELECT * FROM member
と出力されます。
処理の流れは以下のとおりです。
1: table 変数に book をセット
2: text 変数に SELECT * FROM ${table} をセット(table変数の中身はここでは見ない)
3: table 変数の内容を member に書き換え
4:
sh -c "echo \"$text\""
を実行、shが立ち上がり、
echo "SELECT * FROM ${table}"
を実行する。(ここでtableが初めて展開される)
query 変数に、echo が出力した SELECT * FROM member をセットする。(ここでは変数代入だけで画面には出力されない)
5: query 変数の内容、SELECT * FROM member を表示する
あまりやらないですが、こういう複雑な処理でも期待通り動作するのは、適切にクオートしているおかげですね。