文字列リテラルと '\'
'\n' などの 特殊文字を特殊文字と扱いたくないとき、Python では raw string(生文字列)を使う。
文字列の最初の ' または " の直前に r をつければ、スクリプト内の表記通りの文字列として扱われる。
>>> print '[\t]' [ ] >>> print r'[\t]' #raw string [\t]
内部的には \ をエスケープしている。
>>> print repr('[\t]') '[\t]' >>> print repr(r'[\t]') '[\\t]' # \ を重ねて \ 自体をエスケープしてる。
raw string を使わずに同じことをしたければ、明示的に \ を重ねる。
>>> print '[\\t]' [\t] >>> print repr('[\\t]') '[\\t]'
ここまでの理屈は分かりやすい。
エスケープシーケンスと認識できない \ は勝手にエスケープされる。
この場合、r をつけてもつけなくても同じことになる。
>>> print '\z', r'\z' \z \z >>> print repr('\z'), repr(r'\z') '\\z' '\\z'
ちょっと直感に反する気がするけど、仕様だからそういうものだと思うしかない。
ちなみにこのケースは言語によって扱いが違う。
Perl や Rubyの場合、エスケープと認識できない \ は削除される。
#[Ruby] irb(main):001:0> puts "\z" z => nil
なお、Perl, Ruby ではシングルクォートで文字列を記述すると、raw string 扱いとなり、Python のraw stringと同じ挙動になる。
C/C++やJavaでは raw string という概念が無いので、"\z" などはコンパイルエラーになる。
文字列終端の \ は raw string に出来ない
これもまた特殊ケースとなる。
# \ 直後の ' がエスケープされてしまい文字列が終わっていないことになる。 >>> print 'abc\'
↑ は当然だけど、↓ はかなり戸惑った。
>>> print r'abc\' SyntaxError: EOL while scanning single-quoted string
文字列末尾でも raw string では \ をエスケープしていいと思うんだけどダメらしい。何か理由があるのかな。
これに関しては Perl も Ruby も同じ。
raw string に頼らず、明示的に \ を重ねれば期待通りにできる。
>>> print 'abc\\', repr('abc\\') abc\ 'abc\\'
replaceの \ 地獄
最後の仕様のせいで、\ の replace などは見にくくなってしまう。
hoge_string.replace('\\', '\\\\')
どうしても許せなければ、↓こうでもするしかない。
bslash = '\\' hoge_string.replace(bslash, bslash * 2)
せめて string モジュールに back_slash定数が欲しかったな。
追記
C++0xでは raw string があるみたい。http://d.hatena.ne.jp/faith_and_brave/20071102/1194012296