10

Unicode文字列で無効なxml1.0文字を検出するための正規表現があります。

bad_xml_chars = re.compile(u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD\U00010000-\U0010FFFF]', re.U)

Linux / python2.7では、これは完全に機能します。Windowsでは、次のことが発生します。

  File "C:\Python27\lib\re.py", line 190, in compile
    return _compile(pattern, flags)
  File "C:\Python27\lib\re.py", line 242, in _compile
    raise error, v # invalid expression
  sre_constants.error: bad character range

これがWindowsでコンパイルされない理由はありますか?

4

3 に答える 3

16

Windows上に狭いPythonビルドがあるため、UnicodeはUTF-16を使用します。\uFFFFこれは、Python文字列で2文字以上のUnicode文字が使用されることを意味します。次のように表示されます。

>>> len(u'\U00010000')
2
>>> u'\U00010000'[0]
u'\ud800'
>>> u'\U00010000'[1]
u'\udc00'

正規表現エンジンがナロービルドで文字列を解釈しようとする方法は次のとおりです。

[^\x09\x0A\x0D\u0020-\ud7ff\ue000-\ufffd\ud800\udc00-\udbff\udfff]

\udc00-\udbffここで、無効な範囲メッセージの送信元を確認できます。

于 2012-12-13T18:03:56.120 に答える
7

WindowsバージョンのPythonは16ビットを使用して、UTF-16としてエンコードされたUnicode文字を表すため、機能しません。10000UTF-16では、コードポイント以上は2つのコード単位として表されます。reこれにより、の両側に1文字が必要な範囲表現が混乱します-

これは、渡す文字列が文字にre.compile分割される方法です。

>>> [x for x in u'[^\x09\x0A\x0D\u0020-\uD7FF\uE000-\uFFFD\U00010000-\U0010FFFF]']
[u'[', u'^', u'\t', u'\n', u'\r', u' ', u'-', u'\ud7ff', u'\ue000', u'-', 
 u'\ufffd', u'\ud800', u'\udc00', u'-', u'\udbff', u'\udfff', u']']

\U00010000-\U0010FFFFこれは5文字で表されていることに注意してください。

u'\ud800', u'\udc00', u'-', u'\udbff', u'\udfff'

文字セット内で、[...]これを文字と、および範囲re.compileとして解釈します。この範囲は、終了が開始よりも小さいため無効であり、エラーが発生します。u'\ud800'u'\udfff'u'\udc00' - u'\udbff'

于 2012-12-13T18:03:41.197 に答える
1

標準ライブラリには、不正な文字範囲を処理するセクションがあります(Lib/sre_compile.py:450):

if code1[0] != LITERAL or code2[0] != LITERAL:
    raise error, "bad character range"
lo = code1[1]
hi = code2[1]
if hi < lo:
    raise error, "bad character range"

lo文字範囲のとhiリテラルを比較すると、それぞれ\U00010000-\U0010FFFF序数とになります(範囲が逆に見えるため、もちろん失敗します)。5632056319

他の人が言っているように、これはPythonが8文字のUnicodeリテラルを2つの別々の文字として扱っているためです。

于 2012-12-13T18:09:54.803 に答える