2013-05-14 56 views
1

Python將\ uxxxx作爲字符串文字內的Unicode字符轉義(例如,u「\ u2014」被解釋爲Unicode字符U + 2014)。但我剛剛發現(Python 2.7)標準正則表達式模塊不會將\ uxxxx當作unicode字符。例如:python re(regex)是否有一個替代 u的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) 

顯然,如果你可以指定你的正則表達式作爲一個字符串,那麼你可以有同樣的效果,如果正則表達式引擎本身理解爲\ uXXXX轉義:

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) 

但如果你需要動態構建你的模式呢?

+1

您正在創建一個字符串''\ u%s「,然後插入代碼點,並且*不*首先被解釋爲'\ u ....'。這是*預期的行爲*。改用'u'%s'%unichr(codepoint)'。 – 2013-05-14 11:16:20

回答

1

一種可能性是,不是直接調用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) 

它的實例工作:

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 

感謝Process escape sequences in a string in Python您指出的解碼( 「unicode_escape」)的想法。

但請注意,你不能只通過解碼(「unicode_escape」)拋出你的整個模式。它會在一段時間內工作(因爲大多數正則表達式特殊字符在前面加反斜槓時不會改變它們的含義),但它通常不起作用。例如,這裏使用的解碼(「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) 
4

使用unichr() function創建從一個碼點Unicode字符:

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

這是我的例子的一個很好的解決方案。但是這也讓我意識到,我的例子並沒有舉例說明我真正希望問的問題。我不太在意將單個代碼點注入已知形式的字符串,更關心如何處理任意字符串內的不確定數量的\ u轉義。這就是我試圖用我自己的答案進入的方向 - 雖然也許我應該使用unichr作爲其中的一部分。 – Chris 2013-05-14 11:29:39

+0

@Chris:我覆蓋了替換**只是**'\ uxxxx'使用正則表達式在[此前的答案]轉義(http://stackoverflow.com/questions/14367369/unescape-unicode-escapes-but-not-回車符號和線的飼料合蟒/ 14367455#14367455)。 – 2013-05-14 14:22:38

+0

''%s $「'是什麼意思? – alvas 2013-10-17 12:31:27