8

python 3に、いくつかのUnicode表現を含む文字列があります。次に例を示します。

t = 'R\\u00f3is\\u00edn'

そして、tを変換して、印刷時に適切に表現されるようにします。つまり、次のようになります。

>>> print(t)
Róisín

ただし、元の文字列を取り戻すだけです。re.subや他のいくつかを試しましたが、それぞれを繰り返すことなく、これらの文字を変更する方法を見つけることができないようです。そうするための最も簡単な方法は何でしょうか?

4

3 に答える 3

16

組み込みのコーデックを使用しますunicode_escape

tがすでにbytes(8ビット文字列)の場合は、次のように簡単です。

>>> print(t.decode('unicode_escape'))
Róisín

tすでにUnicodeにデコードされている場合は、この方法でエンコードしてからbytesに戻すことができますdecode。すべてのUnicode文字がエスケープされていることが確実な場合は、実際には、エンコードに使用するコーデックは関係ありません。それ以外の場合は、元のバイト文字列を取り戻そうとすることもできますが、エンコードされていない文字を強制的にエンコードすると、すでにエンコードされている文字と一緒にデコードされる方が簡単で、おそらく安全です。

>>> print(t.encode('unicode_escape').decode('unicode_escape')
Róisín

将来、正規表現を使用してこの種のことを行う方法を知りたい場合subは、のパターンの代わりに関数を渡すことができることに注意してくださいrepl。また、を呼び出すことint(hexstring, 16)で任意の16進文字列を整数に変換し、を使用して任意の整数を対応するUnicode文字に変換できますchr(これはPython 2とは異なる1ビットであることに注意してくださいunichr。代わりに必要です)。それで:

>>> re.sub(r'(\\u[0-9A-Fa-f]+)', lambda matchobj: chr(int(matchobj.group(0)[2:], 16)), t)
Róisín

または、もう少し明確にします。

>>> def unescapematch(matchobj):
...     escapesequence = matchobj.group(0)
...     digits = escapesequence[2:]
...     ordinal = int(digits, 16)
...     char = chr(ordinal)
...     return char
>>> re.sub(r'(\\u[0-9A-Fa-f]+)', unescapematch, t)
Róisín

コーデックは、unicode_escape実際には、、、 8進数()、および特殊文字()シーケンスだけでなく、を処理し、適切な最大桁数(4は4、8はなど)のみを読み取るための適切なルールを実装します。 )ではなく、そしておそらく私が考えていなかったより多くのこと。しかし、これはあなたにアイデアを与えるはずです。\U\x\X\066\n\u\u\Ur'\\u22222''∢2'''

于 2012-12-10T02:06:40.270 に答える
0

まず第一に、何に変換するかはかなり混乱しています。

'o'と'i'に変換したいと思うかもしれないと想像してみてください。この場合、マップを作成するだけです。

mp = {u'\u00f3':'o', u'\u00ed':'i'}

あなたが次のように交換を適用することができるより:

t = u'R\u00f3is\u00edn'
for i in range(len(t)):
    if t[i] in mp: t[i]=mp[t[i]]
print t
于 2012-12-10T02:03:39.447 に答える
0

2番目の回答として投稿して申し訳ありません。abarnertのソリューションについてコメントするという評判はありません。

彼の関数を使用して約50KのAndroid文字列を処理した後、特定のユースケースでさらに別の小さな改善が可能であることに気付きました。

有効な16進文字が4桁のエスケープの後に続く場合に対処するために、+を{1,4}に変更しました。

また、int(escapesequence)をint(digits)を読み取るように変更しました

>>> def unescapematch(matchobj):
...     escapesequence = matchobj.group(0)
...     digits = escapesequence[2:]
...     ordinal = int(digits, 16)
...     char = unichr(ordinal)
...     return char

>>> print re.sub(r'(\\u[0-9A-Fa-f]{1,4})', unescapematch, "Wi\u2011Fi")
Wi‑Fi

>>> print re.sub(r'(\\u[0-9A-Fa-f]+)', unescapematch, "Wi\u2011Fi")
Traceback (most recent call last):
  File "<pyshell#102>", line 1, in <module>
    print re.sub(r'(\\u[0-9A-Fa-f]+)', unescapematch, "Wi\u2011Fi")
  File "C:\Python27\lib\re.py", line 151, in sub
     return _compile(pattern, flags).sub(repl, string, count)
  File "<pyshell#99>", line 5, in unescapematch
    char = unichr(ordinal)
ValueError: unichr() arg not in range(0x10000) (narrow Python build)
于 2014-07-19T00:17:48.873 に答える