テスト中など、名前に唯一性のあるファイルを複数個保持したいケースがあります。そんな時、自動でタイムスタンプをつけたり、ファイル名に変数を使えれば便利ですが、これには各種クォートによる装飾が必要です。
ここではクォートの機能と使い方を見ていきます。
クォートとは
文章においてはいわゆる引用符ですが、シェルスクリプトにおいては、囲まれた内容について特別な処理を行います。
クォートは以下の3つに分かれます。
3つのシェルのクォート
- シングルクォート 「’ ’」:
囲んだ内容をそのままの文字列として出力。 - ダブルクォート 「””」:
囲んだ内容に変数がある場合は中身を展開し、文字列として出力 - バッククォート 「``」:
囲んだ内容のコマンドを、同じ行の他のコマンドより先に解釈して実行する
バッククォートに関しては、前半2つのクォートと用途がやや異なり、コマンドに用います。
それぞれ見ていきましょう。
シングルクォート「’」
シングルクォートで囲まれた中身はすべてそのままの文字列として出力されます。これがシェルのクォーテーションの中では一番強力なものになります。
内部に変数が含まれている場合でも、すべてエスケープされて中身は展開されません。
1 2 3 4 5 |
[root@CentOS7 ~]# site_name="Beエンジニア" [root@CentOS7 ~]# echo ${site_name} Beエンジニア [root@CentOS7 ~]# echo '${site_name}' 👈 変数として展開できない ${site_name} |
シングルクォートでもエスケープ出来ないのは、このシングルクォートだけになります。
シングルクォート「’」とバッククォート「`」は取り違えないように注意しましょう。見た目は似ていますが機能は全く異なります。
なお、シングルクォートの中にシングルクォートがある場合、エスケープされて通常表示されません。なんのこっちゃ?・・
# シングルクォートで囲まれたシングルクォート
echo ' ' '
つまり、上記の例のような「’(シングルクォート)」で囲まれた「’(シングルクォート)」は、文字列として認識できないと言う事です。
1 2 |
[root@CentOS7 ~]# echo ''' > 👈 クォートのミスマッチ(数が合わない) |
ダブルクォート「”」
ダブルクォートは、ほとんどの特殊文字の意味をエスケープし、文字として扱います。
「”(ダブルクォート)」の場合は、シングルクォートと異なり、内部に変数が存在する場合はそれを展開して文字列を出力します。
1 2 3 4 5 |
[root@CentOS7 ~]# site_name="Beエンジニア" [root@CentOS7 ~]# echo ${site_name} Beエンジニア [root@CentOS7 ~]# echo "${site_name}" 👈 変数として展開可能 Beエンジニア |
「‘(バツククォート)」、「\(バックスラッシュ)」等の特殊文字はダブルクォートで囲んでも、エスケープすることは出来ません。エスケープが必要な場合は「’(シングルクォート)」で囲みます。例)「echo ' / '」
バックスラッシュ(\)
クォートとは異なりますが、シングルクォートの項目でも説明したように、シングルクォート内のシングルクォートは表示されないため、「Test 'is' done」のような文字列を出力する時には、工夫が必要です。
このような時にはバックスラッシュ(\)を使い、シングルクォート直前につければ出力させることが出来ます。しかし以下の例のように少し複雑に書くことになります。
$ echo 'Test '\''is'\'' done'
「\(バックスラッシュ)」は次の特殊文字をエスケープして、普通の文字として扱います。
1 2 |
[root@CentOS7 ~]# echo 'Test '\''is'\'' done' Test 'is' done |
シェルスクリプトでは、特にこの「\(バックスラッシュ)」によるエスケープ処理は、多用することが多いので頭の片隅に置いておきましょう。
コマンド置換とは
コマンド置換とは、ある行の他のコマンドよりも先行して別のコマンドを実行したいときに行う処理で、先述したバッククォートか、$(command)の形でコマンドを囲んで記述することで実現する事が出来ます。
例えば、サーバー名を末尾に持つファイルを作りたい時には以下のようなコマンドを実行します。
$ touch "file_`uname -n`"
または
$ touch "file_$(uname -n)"
上記コマンドを実行した場合、作られるファイル名はいずれも「file_<ホスト名>」と言うファイルが作成されます。それぞれの記述の違いを見ていきましょう。
バッククォート「`」によるコマンド置換
先の例で出したように、バッククォートでコマンドを囲むことで記述します。
$ DATE=`date`
$ echo $DATE
1 2 3 |
[root@CentOS7 ~]# DATE=`date` [root@CentOS7 ~]# echo ${DATE} 2020年 4月 19日 日曜日 16:27:45 JST |
バッククォートはネストする事が可能ですが、2つ以上の場合はその分だけバックスラッシュを入れ子にしたエスケープが必要です。
$ echo "aaa `echo bbb \`echo ccc\``"
1 2 |
[root@CentOS7 ~]# echo "aaa `echo bbb \`echo ccc\``" aaa bbb ccc |
もし複数回ネストしたい場合は、次に示す$()での記述が簡潔で良いでしょう。
「$()」によるコマンド置換
バッククォートの場合と同様に、コマンドを"$("と")"の記号で囲むことで記述します。ネストしたい場合はエスケープは用いず、単純に$()を内側に書けば実現できます。
いわば「$( )」は、バッククォートの代替機能となります。「上位互換」と言っても過言ではありません。
コマンドの書式
$( コマンド )
# $()によるコマンド置換
$ echo "aaa $(echo bbb)"
# $()によるネストコマンド置換
$ echo "aaa $(echo bbb $(echo ccc))"
1 2 3 4 |
[root@CentOS7 ~]# echo "aaa $(echo bbb)" aaa bbb [root@CentOS7 ~]# echo "aaa $(echo bbb $(echo ccc))" aaa bbb ccc |
クォートやコマンド置換は組み合わせて使用可能なため、状況に応じて簡潔な記述で意図を達成するよう心掛けましょう。
「`(バッククォート)」は古い形式であり、「’(シングルクォート)」と非常に紛らわしいため、可能なら「$( )」を積極的に使用していきましょう。なお「‘(バッククォート)」と「$( )」の機能に差はありません。
Shellスクリプト基礎知識(全11記事+1)
├─シェルスクリプトの基本事項!
├─変数と特殊変数について!
├─演算子「算術演算子」「比較演算子」について!
├─条件分岐「if」「case」について!
├─ループ処理「for」「while」について!
├─文字列置換「bash」「sed」について!
├─複数行のテキスト出力!ヒアドキュメントについて!
├─書式?戻り値?シェルスクリプト内の関数について!
├─シェルの組み込みコマンドについて!
├─クォートとは?コマンド置換とは?実現方法と内容の違いについて!
└─リダイレクトとは?標準入力・出力、標準エラー出力等について!
(補足)シェルスクリプトの設計書とは?必要な項目や書き方等を解説!