Bashの文字列で特殊文字を使う方法

2020/02/20更新

目次

概要

Bashで、タブをgrepしようとしてgrep -e "\t" file.txtとしてもうまくいかない。また、シングルクォートの中でシングルクォートを記述しようとして、echo 'I don\'t know.'などとしてもやはりうまくいかない。このように、Bashにおける文字列のクォートでは、他のプログラミング言語でよく使われている\によるエスケープ記法が使えず、特殊文字を記述したくなったとき初めは戸惑ってしまう。そこで、Bashにおいて特殊文字を記述したい場合の方法をここにまとめておく。

Bashにおける文字列のクォート

Bashで、ダブルクォートとシングルクォートの主な使い分けは、変数展開をするかどうかである。シングルクォートは\によるエスケープは一切使えないため、'を記述することは不可能となる。また、特殊文字もそのものを直接入力するしかない。ダブルクォートの中では、"など一部の文字は\によるエスケープが使えるものの、特殊文字などはやはり直接入力するしかない。

一方で、クォートの外では、$'~'という記法によって、よくあるC言語スタイルの\によるエスケープを記述できる。実はこれは「クォートの外」ではなく、$'~'という別の種類のクォート(ANSI-C Quoting)である。

Bashでは文字列を連結する演算子は特に無く、ただ並べて書けば自動的に文字列が連結される。そのため、必要に応じてこれらのクォートを文字列の途中で使い分ければよい。

ダブルクォートの中

シングルクォートの中

クォートの外

改行

直接入力

直接入力

$'\n'

タブ

直接入力(※1)

直接入力(※1)

$'\t'

その他の制御文字

直接入力(※2)

直接入力(※2)

$'\e'$'\x09'など。

ダブルクォート "

\"

"

\"

シングルクォート '

'

(不可)

\'

バッククォート`

\`

`

\`

バックスラッシュ \

\\または\

\

\\

ドル $

\$

$

\$

なお、コマンド置換で使われるバッククォート`~`は、文字列のためのクォートではないため、その中は基本的にクォートの外と同じであるが、`\はエスケープする必要があるため、バッククォートの中でバッククォートを使う場合は注意が必要である。

タブ文字をgrepしたい

ANSI-C Quotingで\tを使うか、または直接入力すればよい。以下の例で、空白のように見える部分は、実際にはタブ文字を直接入力する。

# タブを検索
grep -e $'\t' file.txt
grep -e "    " file.txt

# タブを含む文字列を検索
grep -e hoge$'\t'fuga file.txt
grep -e "hoge    fuga" file.txt

# タブから始まる行を検索
grep -e ^$'\t' file.txt
grep -e "^    " file.txt

シングルクォートの中でシングルクォートを使いたい

シングルクォートの中でシングルクォートは使えない。シングルクォートの部分だけ別のクォートを使うか、クォートを閉じて裸で\'と記述すればよい。

# クォートを一度閉じて裸で\'と書く。
echo 'I don'\''t know.'

# シングルクォートの部分だけダブルクォートにする。
echo 'I don'"'"'t know.'

改行を含む文字列を変数に代入したい

ANSI-C Quotingで\nを使うか、または可読性は落ちるが直接記述することもできる。

# $'~'を使う。
str=hoge$'\n'fuga
str=$'hoge\nfuga'

# クォートの中で直接改行する。
str="hoge
fuga"

改行を含む文字列をechoしたい

前述のようにして改行を含む文字列を代入した変数をechoする場合は、ダブルクォートで囲む必要がある。あるいは、echoコマンドの場合は、-eオプションを使うことで、見慣れた\によるエスケープを直接使用することもできる。

str1=hoge$'\n'fuga
str2='hoge\nfuga'

echo "$str1"
# hoge
# fuga

echo "$str2"
# hoge\nfuga

echo -e $str2
# hoge
# fuga

制御文字をechoしたい

エスケープシーケンスによって文字色をつけるなどの目的で制御文字を出力したい場合は、ANSI-C Quotingを使えばよい。

echo $'\e[31mhoge\e[0m'
# 赤い文字の「hoge」が出力される

バッククォートを使いたい

バッククォート`はシングルクォートの中以外ではコマンド置換になってしまうため、\`とエスケープする必要がある。バッククォートの中でバッククォートを文字列として使う場合は、二重にエスケープが必要となるので注意が必要である。ちなみに、バッククォートによるコマンド置換はネスト(入れ子)ができないと思われがちだが、実はこのように適切にエスケープをすれば(大変な労力が伴うので通常は推奨されないが)ネストをすることは可能である。

# 以下はいずれも「`」を出力する
echo \`
echo '`'
echo "\`"
echo `echo \\\``
echo `echo '\`'`
echo `echo \`echo \\\\\\\`\``

# 以下はエスケープが不適切なため、いずれもエラーとなる
echo `
echo "`"
echo `echo \``
echo `echo '`'`

外部リンク