本記事はシェルスクリプトで見られる
クォテーション('や"など)の記法についてまとめています.
種類
クォテーションは以下の4種類です.
- シングルクォート:
' - ダブルクォート :
" - バッククォート :
` - バックスラッシュ:
\
前提知識
ここでは前提となる内容を記載しています.
各クォテーションの意味をさっと知りたい方は読み飛ばしても大丈夫です.
確認する場合はこちらをクリック
シェルは様々な文字や記号を読み解いて処理していきますが,一部の記号はシェルが特別の解釈をします.
この特別の解釈をする記号を総称して「特殊文字」や「メタキャラクタ」と呼びます.
(特殊文字には「$や*」など,多くの記号があります)
シェルは特殊文字が存在すると,その特殊文字に応じた解釈をします.
そのため特殊文字を普通の文字として解釈して欲しい場合,そのための目印が必要であり,その目印として使用する記号がクォテーションです.
すなわちクォテーションはシェルの解釈のうまく誘導してあげて,こちらが意図したとおりに挙動させるために使います.
【具体例】
$は$の後に続く変数を展開して表示するための特殊文字です.
例えばある変数を定義して,変数の中身を表示したい場合は以下のように記述します.
KANI=100
echo $KANI
100
では「$100」という「文字」を表示させたい場合を考えます.
以下のコードを見てみましょう.
echo $100
上記のコマンドでは結果が何も表示されないのです・・・
これはシェルが$を特別に解釈して$の後の100という変数を展開するためです.
しかし100という変数は定義していないので中身はありません.そのため空白が表示されています.
ここでクォーテーションの出番です.
今回$は普通の文字として扱って欲しいので,それをシェルに伝えるためにシングルクォートを使用したものが以下のコードです.
echo '$100'
$100
シングルクォートで囲まれた部分はただの文字として解釈されるので,こちらの意図どおりの出力を得ることができました.
以上のような感じでクォテーションを使用します.
クォテーションは複数あり,それぞれの意味があるので本記事ではそうした違いを見ています.
各クォテーションの違い
シングルクォート
シングルクォート(')で囲まれた文字はすべて1「普通の文字」として解釈されます.
そのため,シェルによる特殊文字の解釈を一切させない場合に用います.
「書いたとおりに解釈してね」ということです.
echo '$KANI'
$KANI
結果を見ると,シングルクォートで囲まれた文字がそのまま出力されていますね.
唯一の例外は'(シングルクォート自身)だけです.
以下のコマンドを実行するとエラーこそ出ませんが,変な表示が出てきます.
(quote>を抜けるにはCtrl+C)
echo 'KANI's book'
quote>
シングルクォートを含む文字をそのまま表示させたい場合はダブルクォートで囲みます.
echo "KANI's book"
KANI's book
こちらの意図どおり出力されましたね.
ダブルクォート
ダブルクォート(")で囲まれた文字列は原則「普通の文字」として解釈されます.
しかし$と`, \, "(ダブルクォート自身)は例外です.
シングルクォートと比較しながら見てみましょう.
まずは変数への代入とシンプルな出力です.
KANI=100
echo $KANI
100
結果には変数KANIが展開されて表示されています.
次にシングルクォートの場合を見てみます.
echo '$KANI'
$KANI
シングルクォートは強いので囲んだものを文字として解釈させます.
そのため,$KANIがそのまま出力されています.
最後にダブルクォートです.
echo "$KANI"
100
ダブルクォートは$を特殊文字としてシェルに解釈させるため,変数の展開が実行された結果が出力されます.
参考:echo $KANIとecho "$KANI"の違い(クリックで展開されます)
先ほど確認したecho $KANIとecho "$KANI"はいずれも出力結果が同じです.
「どっちでも同じならいちいち"で囲まなくてもいいのでは?」となりそうですが,囲まない場合は展開する変数にスペースが含まれないことが前提です.2
"で囲まないとスクリプトが動かない例を見てみましょう.
#!/bin/bash
category='dog cat'
if [ $category = "dog cat" ]; then
echo 犬猫!
fi
このシェルスクリプトは変数categoryがdog catなら「犬猫!」と表示するだけのものです.
これをtxt.shとして保存・権限付与をして実行すると以下のようなエラーが発生します.
./tst.sh: line 5: [: too many arguments
これはif文の判定式[ $category = "dog cat" ]の$categoryが原因です.
原因を探るために変数展開後の判定式を以下で見てみましょう.
[ dog cat = "dog cat" ]
dog catに半角スペースが含まれているため,シェルがそれを解釈し余計な引数あるということでエラーになっていました.
これを解消するにはスクリプトを以下のように修正します.
#!/bin/bash
category='dog cat'
# $categoryを"で囲む
if [ "$category" = "dog cat" ]; then
echo 犬猫!
fi
これで変数展開された後の判定式は次のようになるため,エラーなく処理を実行できます. (文字列同士の比較になっているためエラーが発生しません)
[ "dog cat" = "dog cat" ]
以上を踏まえると,変数展開を行う際は基本的に"で囲っておくと安心です.
なお,先述したとおりecho $KANIとecho "$KANI"に関してはスペースの有無でエラーになることはありません.
これはechoコマンドが引数の文字をそのまま出力するため,半角スペースがあっても引数が複数あると解釈してそのまま出力してくれるためです.
シェルの種類に注意
上記で確認した内容はシェルがbash, shの場合です.
Macのデフォルトシェルzshは最初のスクリプトでもエラーなく実行されます.
ダブルクォートは囲んだ文字列について変数やコマンドの置き換えを行う場合に使用するケースが多いです.
date
2022年 4月 2日 土曜日 12時12分17秒 JST
dateは現在日時を表示してくれるコマンドなので,結果を見ると日時が表示されています.
echo 'ただいまの日時は`date`'
ただいまの日時は`date`
シングルクォートで囲まれた部分は文字3として解釈されるのでそのまま表示されています.
echo "ただいまの日時は`date`"
ただいまの日時は2022年 4月 2日 土曜日 12時12分17秒 JST
ダブルクォートの場合は`を解釈するためコマンドが実行されます.
上記の例はコマンドの置き換えを行なったものです.
ダブルクォートを使うことでコマンドの実行結果と文字列を組み合わせて表示できています.
ここで使用している`(バッククォート)については次項で解説しています.
なお"を普通の文字として扱いたい場合は"で囲まず,シングルクォートで囲みます.
次の2つのコマンドで確認しましょう.
echo "KANI said "hoge""
KANI said hoge
"を含む文字を"で囲むとKANI said "hoge"とはなりませんでした.
"を含む文字を'で囲むと・・・
echo 'KANI said "hoge"'
KANI said "hoge"
シングルクォートで囲むと意図どおりに表示されました.
バッククォート
バッククォート(`)は先の例のとおり,コマンドを囲むことでそのコマンドを実行して置き換えます.
echo "こんにちは`echo KANI`さん"
こんにちはKANIさん
`で囲まれた部分のコマンドが実行されてKANIに置き換わり表示されています.
バッククォートは色々と応用の幅があるので記法を知っておくと便利です.
バックスラッシュ
バックスラッシュ(\)は特殊文字を解釈させないために使用します.
具体的にはバックスラッシュ直後の特殊文字の意味を剥奪します.
KANI=100
echo $KANI
100
上記のコードでは$をつけて変数展開を行っています.
この$の意味を取り除いてただの$とするには以下のようにします.
echo \$KANI
$KANI
\を$の前につけることで$の意味を剥奪しています.
結果として$が特殊文字として解釈されないためそのまま表示されます.
ところで,バックスラッシュは直後の文字にしか効果がありません.
そのため,以下のように記載すると最初の$は意味を剥奪されますが,次の$は特殊文字として機能するため変数が展開されます.
echo \$$KANI
$100
ちなみに\を2つ使って以下のように書けば両方の$の意味が剥奪されます.
echo \$\$KANI
$$KANI
ただし,上記のような結果($$KANI)を得たいのであればecho '$$KANI'で事足ります.
複数のバッククォートを使う場合は正規表現などでよく見られるので,気になる方は調べてみましょう.
ひとこと
本記事ではクォテーションに関する基本的な部分を解説しました.
クォテーションの使い方は様々なものがあるため,色々とパターンを学んでいきたいですね.