python re(正则表达式)是否有\u unicode转义序列的替代方案?

python re(正则表达式)是否有\u unicode转义序列的替代方案?,python,regex,unicode,python-unicode,unicode-escapes,Python,Regex,Unicode,Python Unicode,Unicode Escapes,Python将\uxxx视为字符串文本中的unicode字符转义(例如,u“\u2014”被解释为unicode字符u+2014)。但我刚刚发现(Python2.7)标准正则表达式模块没有将\uxxx作为unicode字符处理。例如: codepoint = 2014 # Say I got this dynamically from somewhere test = u"This string ends with \u2014" pattern = r"\u%s$" % codepoint

Python将\uxxx视为字符串文本中的unicode字符转义(例如,u“\u2014”被解释为unicode字符u+2014)。但我刚刚发现(Python2.7)标准正则表达式模块没有将\uxxx作为unicode字符处理。例如:

codepoint = 2014 # Say I got this dynamically from somewhere

test = u"This string ends with \u2014"
pattern = r"\u%s$" % codepoint
assert(pattern[-5:] == "2014$") # Ends with an escape sequence for U+2014
assert(re.search(pattern, test) != None) # Failure -- No match (bad)
assert(re.search(pattern, "u2014")!= None) # Success -- This matches (bad)
显然,如果您能够将正则表达式模式指定为字符串文字,那么您可以获得与正则表达式引擎本身理解\uxxx转义相同的效果:

test = u"This string ends with \u2014"
pattern = u"\u2014$"
assert(pattern[:-1] == u"\u2014") # Ends with actual unicode char U+2014
assert(re.search(pattern, test) != None)

但是,如果需要动态构建模式,该怎么办呢?

一种可能性是,不要直接调用re方法,而是将它们包装在能够理解\u代表它们转义的东西中。大概是这样的:

def my_re_search(pattern, s):
    return re.search(unicode_unescape(pattern), s)

def unicode_unescape(s):
        """
        Turn \uxxxx escapes into actual unicode characters
        """
        def unescape_one_match(matchObj):
                escape_seq = matchObj.group(0)
                return escape_seq.decode('unicode_escape')
        return re.sub(r"\\u[0-9a-fA-F]{4}", unescape_one_match, s)
it工作示例:

pat  = r"C:\\.*\u20ac" # U+20ac is the euro sign
>>> print pat
C:\\.*\u20ac

path = ur"C:\reports\twenty\u20acplan.txt"
>>> print path
C:\reports\twenty€plan.txt

# Underlying re.search method fails to find a match
>>> re.search(pat, path) != None
False

# Vs this:
>>> my_re_search(pat, path) != None
True
感谢您指出解码(“unicode_escape”)的想法

但请注意,您不能只是将整个模式进行解码(“unicode_escape”)。它会在某些时候起作用(因为大多数正则表达式特殊字符在前面加反斜杠时不会改变它们的含义),但通常不会起作用。例如,这里使用decode(“unicode_escape”)改变正则表达式的含义:

pat = r"C:\\.*\u20ac" # U+20ac is the euro sign
>>> print pat
C:\\.*\u20ac # Asks for a literal backslash

pat_revised  = pat.decode("unicode_escape")
>>> print pat_revised
C:\.*€ # Asks for a literal period (without a backslash)
使用从代码点创建unicode字符:

pattern = u"%s$" % unichr(codepoint)

您首先创建一个字符串
'\u%s
,然后插入码点,而这不会被解释为
\u…
。这是意料之中的行为。改为使用
u'%s'%unichr(codepoint)
。这是我的示例的一个很好的解决方案。但这也让我意识到,我的例子并没有说明我真正想问的问题。我不太关心将单个代码点注入到已知形式的字符串中,而更关心如何处理任意字符串中数量不明的\u转义。这就是我试图给出自己答案的方向——尽管也许我应该使用unichr作为其中的一部分。@Chris:我在中介绍了使用正则表达式替换转义符。
%s$”
是什么意思?@alvas:
%s
是字符串插值的占位符;它被表达式
unichr(codepoint)
的输出替换
$
是一个正则表达式元字符,表示“在行尾匹配”。