Pythonでエスケープシーケンスを無視(無効化)するraw文字列

Modified: | Tags: Python, 文字列

Pythonで文字列リテラル'...', "..."の前にrまたはRをつけると、エスケープシーケンスを展開せずそのままの値が文字列となる。Windowsのパスや正規表現のパターンなど、バックスラッシュを多用する文字列を扱うときに便利。

エスケープシーケンス

Pythonでは、通常の文字列では表せない文字(タブや改行など)をC言語などと同様にバックスラッシュ\をつけたエスケープシーケンス(\t\nなど)で記述する。

s = 'a\tb\nA\tB'
print(s)
# a b
# A B

raw文字列でエスケープシーケンスを無視(無効化)

文字列リテラル'...', "..."の前にrまたはRをつけると、エスケープシーケンスを展開せずそのままの値が文字列となる。このような文字列はraw文字列(raw strings, r-strings)と呼ばれる。

rs = r'a\tb\nA\tB'
print(rs)
# a\tb\nA\tB

raw文字列型という特別な型があるわけではなく、あくまでも文字列型で、バックスラッシュを\\で表した通常の文字列と等しい。

print(type(rs))
# <class 'str'>

print(rs == 'a\\tb\\nA\\tB')
# True

通常の文字列ではエスケープシーケンスは1文字とみなされるが、raw文字列ではバックスラッシュも文字数にカウントされる。文字列の長さや各文字は以下のようになる。

s = 'a\tb\nA\tB'

print(len(s))
# 7

print(list(s))
# ['a', '\t', 'b', '\n', 'A', '\t', 'B']
rs = r'a\tb\nA\tB'

print(len(rs))
# 10

print(list(rs))
# ['a', '\\', 't', 'b', '\\', 'n', 'A', '\\', 't', 'B']

Windowsのパス

raw文字列を使うと便利なのが、Windowsのパスを文字列で表したいとき。

Windowsのパスは区切り文字にバックスラッシュ\を使うので、通常文字列ではいちいち\\のようにエスケープしないといけないが、raw文字列ではそのまま書ける。値としては等価。

path = 'C:\\Windows\\system32\\cmd.exe'
rpath = r'C:\Windows\system32\cmd.exe'
print(path == rpath)
# True

なお、後述のように、末尾が奇数個のバックスラッシュで終わる文字列はエラーになるので注意。この場合は通常の文字列で書くか、末尾だけ通常文字列で書いて連結する必要がある。

path2 = 'C:\\Windows\\system32\\'
# rpath2 = r'C:\Windows\system32\'
# SyntaxError: EOL while scanning string literal
rpath2 = r'C:\Windows\system32' + '\\'
print(path2 == rpath2)
# True

repr()で通常の文字列をraw文字列に変換

通常の文字列をエスケープシーケンスを無視(無効化)したraw文字列相当の文字列に変換したい場合、組み込み関数repr()が使える。

s = 'a\tb\nA\tB'

s_r = repr(s)
print(s_r)
# 'a\tb\nA\tB'

repr()が返すのはeval()に渡されたときと同じ値を持つようなオブジェクトを表す文字列であり、先頭と末尾に'が付いている。

print(list(s_r))
# ["'", 'a', '\\', 't', 'b', '\\', 'n', 'A', '\\', 't', 'B', "'"]

スライスを使うとrを付けたraw文字列と等価な文字列が得られる。

rs = r'a\tb\nA\tB'

s_r2 = repr(s)[1:-1]
print(s_r2)
# a\tb\nA\tB

print(s_r2 == rs)
# True
print(r'\t' == repr('\t')[1:-1])
# True

末尾のバックスラッシュに注意

バックスラッシュが直後のクオート文字'または"をエスケープするので、文字列末尾に奇数個のバックスラッシュ\があるとエラーが発生する。偶数個であれば問題ない。

# print(r'\')
# SyntaxError: EOL while scanning string literal

print(r'\\')
# \\

# print(r'\\\')
# SyntaxError: EOL while scanning string literal

関連カテゴリー

関連記事