rcmdnk's blog

文字 (ずかん)

シェルスクリプトを書く時に文字列の中に改行を書く話。 明記がない限り基本的にLinux環境でのBashの話です。

Pythonなどでの改行

シェルスクリプトの前に、Pythonなどの言語では \nが改行コードになっていて、

>>> a = """abc
xyz"""
>>> print(a)
abc
xyz
>>> print(repr(a))
'abc\nxyz'
>>> b = "abc\nxyz"
>>> print(b)
abc
xyz
>>> print(repr(b))
'abc\nxyz'
>>> a == b
True
>>> "\n" in a
True
>>> "\n" in b
True

といった感じに改行を直接書いても文字列中では\nとして入れられて printなどの出力ではそれを変換して出力している形になっています。

大概の言語ではこんな感じになってるかと思います。

シェルスクリプトでの\n

シェルスクリプト中でも\nを入れると出力が改行になることがあります。

$ b="abc\nxyz"
$ printf "$b"
abc
xyz

ただ、echoとかだと

$ b="abc\nxyz"
$ echo "$b"
abc\nxyz

となって\nが残ります。

これはBashのbuiltinのechoであれば

$ b="abc\nxyz"
$ echo -e "$b"
abc
xyz

-eオプションを使えば変換してくれます。

一方で、改行を直接入れると

$ a="abc
xyz"
$ printf "$a"
abc
xyz$ echo "$a"
abc
xyz
$ echo -e "$a"
abc
xyz

とオプションなしのechoでも改行してくれます。

比較して見ると

$ if [ "$a" = "$b" ];then echo SAME;else echo DIFF;fi
DIFF

となって違うものとして保存されていることがわかります。

シェルスクリプトでの$’\n’

Bashでは改行と\nは同義ではないですが、 BashにはANSI-C Quoting という特殊文字があり、この中に $'\n'という 改行が定義されています。

この文字はクォートの中だと通常の文字として認識されてしまうので、その部分だけはクォート外にする必要があります。

$ c="abc"$'\n'"xyz"
$ printf "$c"
abc
xyz$ echo "$c"
abc
xyz
$ echo -e "$c"
abc
xyz

この文字列は実際に改行を書いた場合と比べると

$ if [ "$a" = "$c" ];then echo SAME;else echo DIFF;fi
SAME

ということで同じものとして認識されています。

クォートの中に入れると

$ d="abc$'\n'xyz"
$ printf "$d"
abc$'
'xyz$ echo "$d"
abc$'\n'xyz
xyz
$ echo -e "$d"
abc$'
'xyz

な感じでprintfとかでは$'を単なる文字として認識して\nの部分だけを改行として変換して出力するようになります。

この$'\n'に関しては$'012'もしくは$'x0A'(共に8進法と16進法での10、ASCIIコードでのLF(改行)を表すもの) としても全く同じものとして認識されます。

$ e="abc"$'\012'"xyz"
$ f="abc"$'\x0A'"xyz"
$ if [ "$a" = "$e" ];then echo SAME;else echo DIFF;fi
SAME
$ if [ "$a" = "$f" ];then echo SAME;else echo DIFF;fi
SAME

このANSI-C QuotingはZshなどモダンなシェルではサポートされています。

Ubuntuなどの/bin/shになっているdashなどだとサポートされておらず、

$ dash
$ a="abc
xyz"
$ c="abc"$'\n'"xyz"
$ if [ "$a" = "$c" ];then echo SAME;else echo DIFF;fi
DIFF
$ echo "$a"
abc
xyz
$ echo "$c"
abc$
xyz

みたいな感じで$が単に文字列とみなされ、'\nをクォートしたものとみなされて削除されています。

Sponsored Links
Sponsored Links

« シェルスクリプト(主にBash)で文字列前後のスペースを削除する Python 3.10で導入された構造的パターンマッチで正規表現を使ったmatchを行う »

}