🐚

Bashで展開される文字列と展開される時

2020/11/01に公開

Background

Bash使う時にどう言う文字列がどう言う時に展開されるかちゃんと把握せず、実際書いてみて期待と違ったら書き直す、みたいなことをずっとやってたので1回ちゃんと調べてまとめた。それぞれの展開機能自体の解説はしない[1]

参照したドキュメント(bash v5.0のman)

Main Contents

主な[2]文脈として、 以下がある。

  • unquoted
  • "double quoted"
  • 'single quoted'
  • $'single quoted with dollar'[3]

主な[4]文字列展開として

  • History Expansion(e.g. !!)
  • Parameter Expansion(e.g. ${VAR})
  • Command Substitution(e.g. $(cmd), `cmd` )
  • Arithmetic Expansion(e.g. $((1+1)))
  • Brace Expansion(e.g. a{b,c}d, {1..5})
  • Tilde Expansion(e.g. ~)
  • Pathname Expansion(e.g. dir/*, /dev/video[0-3])
  • Backslash-Escaped Characters[5](e.g. \n)

これらのうちいつどれが展開されるかを表にすると以下。

unquoted " " ' ' $' '
!! o o x x
${VAR} o o x x
$(cmd) o o x x
$((1+1)) o o x x
a{b,c}d o x x x
~ o x x x
dir/* o x x x
\n x x x o

Supplements

HERE DOCUMENTS

以下のようなテキストをHere Documentsと言う

<<HERE
text
HERE

これは $ 系Expansion(${VAR}, $(cmd), $((1+1)))が展開される。 "double quoted" の History Expansionがないバージョン。
また、Here DocumentsにはHEREの部分にsingle quoteをつけることも出来る。

<<'HERE'
text
HERE

この場合、何も展開されない('single quoted'と同じ)。

Backslash-Escaped Characters

$' ' で展開されるbackslash-escaped charactersは以下(manから引用)

\a     alert (bell)
\b     backspace
\e
\E     an escape character
\f     form feed
\n     new line
\r     carriage return
\t     horizontal tab
\v     vertical tab
\\     backslash
\'     single quote
\"     double quote
\?     question mark
\nnn   the eight-bit character whose value is the octal value nnn (one to three octal digits)
\xHH   the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
\uHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits)
\UHHHHHHHH
       the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits)
\cx    a control-x character

echo -eprintf でも backslash-escaped charactersの展開ができる。が、扱える文字列は微妙に違う。以下manから引用。

\a     alert (bell)
\b     backspace
\c     suppress further output
\e
\E     an escape character
\f     form feed
\n     new line
\r     carriage return
\t     horizontal tab
\v     vertical tab
\\     backslash
\0nnn  the eight-bit character whose value is the octal value nnn (zero to three octal digits)
\xHH   the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
\uHHHH the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHH (one to four hex digits)
\UHHHHHHHH
       the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value HHHHHHHH (one to eight hex digits)

$" "

$' ' とは別に $" " もある。これは普通の " " に加えて、 gettext と同じi18nの文字列置換機能が使用できる[6]

$ locale -a
C
C.UTF-8
en_GB.utf8
en_US.utf8
ja_JP.utf8
POSIX

$ export TEXTDOMAIN=bash
$ export LANG=en_US.UTF-8
$ echo $"Done"
Done
$ gettext -s Done
Done

$ export LANG=ja_JP.UTF-8
$ echo $"Done"
終了
$ gettext -s Done
終了

参考: https://www.linuxjournal.com/content/internationalizing-those-bash-scripts

また $" " はbackslash-escaped charactersが展開されない

脚注
  1. けど特にParameter Expansionとかは、あんまり知られてなさそうだけど便利機能がいっぱいなのでshell script書くことがある人はmanを1度見ておくのがおすすめ ↩︎

  2. 独断と偏見 ↩︎

  3. 正式な名前ではない ↩︎

  4. 独断と偏見 ↩︎

  5. 通常展開と言う言葉は使われないが、まとめちゃう ↩︎

  6. localeの設定が必要 ↩︎

Discussion