導入
シェルスクリプトのバグの半分は、クォートが原因です。" と ' と「囲まない」で結果が変わることを、最初にきっちり体に入れておきましょう。ここを曖昧にしたまま先に進むと、あとで必ず遠回りします。
説明
囲み方は3つ。違いは 「中の $変数 を展開するか」 と 「スペースで区切られるか」 です。
| 書き方 | $変数 の展開 | 用途 |
|---|---|---|
"..."(二重引用符) | される | 基本はこれ。値にスペースが入っても1つの値として扱える |
'...'(単一引用符) | されない | $ や * を文字そのものとして扱いたいとき |
| 囲まない | される | 値にスペースがあると複数に割れてしまう(危険) |
#!/bin/bash
name=太郎
message="こんにちは、世界"
echo "二重引用符: $name"
echo '単一引用符: $name'
echo "メッセージは $message です"
実行すると、二重引用符では 太郎 に化け、単一引用符では $name という文字がそのまま出ます。
囲まないと何が困るのか。スペースを含む値が、別々の引数に割れてしまうのです。
flowchart TD
A["message=\"こんにちは 世界\""] --> B["echo $message<br/>(囲まない)"]
A --> C["echo \"$message\"<br/>(囲む)"]
B --> D["引数2つ: こんにちは / 世界"]
C --> E["引数1つ: こんにちは 世界"]
echo では違いが見えにくいのですが、これがファイル名だと事故になります。rm $file で file="大事な メモ.txt" だったら、大事な と メモ.txt の2つを消そうとします。
迷ったら二重引用符で囲む。これが唯一の正解に近いルールです。第7章でもう一度、この落とし穴を扱います。
やってみよう
3つの echo を実行して、" と ' の差を目で確かめてください。そのあと echo $message と echo "$message" の両方をエディタに足して実行し、囲まなくても echo なら同じに見えることも確認しましょう(見えないだけで、内部では割れています)。
演習
$name を展開させずに、$name という文字をそのまま画面に出してください。
ヒント1を見る
$ を文字として扱いたいときは単一引用符 ' で囲みます。
ヒント2を見る
echo '単一引用符: $name'