unicode_escape
一般的には機能しません
string_escape
or unicode_escape
ソリューションは一般的に機能しないことが判明しました。特に、実際のUnicodeの存在下では機能しません。
すべての非ASCII文字がエスケープされることが確実である場合(そして、最初の128文字を超えるものはすべて非ASCIIであることを覚えておいてunicode_escape
ください)、あなたのために正しいことを行います。ただし、文字列にリテラルの非ASCII文字がすでにある場合、問題が発生します。
unicode_escape
基本的に、バイトをUnicodeテキストに変換するように設計されています。しかし、多くの場所(たとえば、Pythonソースコード)では、ソースデータは既にUnicodeテキストです。
これが正しく機能する唯一の方法は、最初にテキストをバイトにエンコードすることです。UTF-8はすべてのテキストに適したエンコーディングであるため、機能するはずです。
次の例はPython 3にあるため、文字列リテラルはわかりやすくなっていますが、Python 2と3の両方でわずかに異なる表現で同じ問題が存在します。
>>> s = 'naïve \\t test'
>>> print(s.encode('utf-8').decode('unicode_escape'))
naïve test
まあ、それは間違っています。
テキストをテキストにデコードするコーデックを使用するための新しい推奨方法は、codecs.decode
直接呼び出すことです。それは役に立ちますか?
>>> import codecs
>>> print(codecs.decode(s, 'unicode_escape'))
naïve test
どういたしまして。(また、上記はPython 2のUnicodeErrorです。)
unicode_escape
コーデックは、その名前にもかかわらず、すべての非ASCIIバイトはラテン1(ISO-8859-1)エンコーディングであると仮定することが判明しました。したがって、次のようにする必要があります。
>>> print(s.encode('latin-1').decode('unicode_escape'))
naïve test
しかし、それはひどいです。これにより、Unicodeがまったく発明されていないかのように、256 Latin-1文字に制限されます。
>>> print('Ernő \\t Rubik'.encode('latin-1').decode('unicode_escape'))
UnicodeEncodeError: 'latin-1' codec can't encode character '\u0151'
in position 3: ordinal not in range(256)
正規表現を追加して問題を解決する
(驚いたことに、現在2つの問題はありません。)
必要なのは、unicode_escape
ASCIIテキストであることが確実なものにのみデコーダを適用することです。特に、ASCIIテキストであることが保証されている有効なPythonエスケープシーケンスにのみ適用できることを確認できます。
計画は、正規表現を使用してエスケープシーケンスを見つけre.sub
、それらをエスケープされていない値に置き換えるための引数として関数を使用することです。
import re
import codecs
ESCAPE_SEQUENCE_RE = re.compile(r'''
( \\U........ # 8-digit hex escapes
| \\u.... # 4-digit hex escapes
| \\x.. # 2-digit hex escapes
| \\[0-7]{1,3} # Octal escapes
| \\N\{[^}]+\} # Unicode characters by name
| \\[\\'"abfnrtv] # Single-character escapes
)''', re.UNICODE | re.VERBOSE)
def decode_escapes(s):
def decode_match(match):
return codecs.decode(match.group(0), 'unicode-escape')
return ESCAPE_SEQUENCE_RE.sub(decode_match, s)
そしてそれで:
>>> print(decode_escapes('Ernő \\t Rubik'))
Ernő Rubik
'spam'+"eggs"+'''some'''+"""more"""
に処理されると思いますか?