2015-01-06 3 views
2

Я читаю регулярное выражение из файла и вообще не было никаких проблем, пока этот один не пришел:Чтение Regex Character Class Тендерный из файла

^X.{0,2}[\u2E80-\u9FFF] # \u2E80-\u9FFF matches most Chinese and Japanese characters 

Регулярное выражение прекрасно работает при компиляции внутри:

p = re.compile(u'^X.{0,2}[\u2E80-\u9FFF]', re.IGNORECASE | re.UNICODE) 
print p.search(u'XFlowers for you') 
>> none 
print p.search(u'X桜桜桜桜') 
>> <match object> 

, но спецификатор диапазона символов, по-видимому, искажен в процессе импорта, поскольку он соответствует практически всему, начиная с X после этого:

f = codecs.open(filename, "r", "utf-8") 
lines = f.read().splitlines() 
filePatterns = FileHelper.fileToList(ignoreFile) 
patternList = [re.compile(x, re.IGNORECASE | re.UNICODE) for x in ignorePatterns] 

for name in [u'XFlowers for you', u'X桜桜桜桜'] 
    for pattern in patternList: 
     print pattern.search(name): 

Это будет соответствовать обеим строкам.

Кто-нибудь знает, как это решить? Спасибо!

+0

только предположение, но я думаю, что кодирование на файл неправильно, попробуйте прочитать его как Юникод или ASCII с ЭСКАТО e sequence – user230910

+0

Я думал, что спецификатор utf-8 принудительно интерпретирует как unicode. Есть ли еще один аспект этого? – Colin

ответ

3

Проблема заключается здесь:

>>> u'^X.{0,2}[\u2E80-\u9FFF]' 
u'^X.{0,2}[\u2e80-\u9fff]' 

против

>>> '^X.{0,2}[\u2E80-\u9FFF]' 
'^X.{0,2}[\\u2E80-\\u9FFF]' 

Обратите внимание на разницу? В первом примере вы получите строку Unicode с действительными символами Unicode (это только отображается как escape-последовательности), вторая дает строку не-Юникод с обратными косыми чертами и синтаксически сломанным классом символов.

Когда вы читаете выражение из файла, вы получаете второй вариант. Вам нужно, чтобы превратить это в строку Unicode - либо сохранить файл как Unicode и используя фактические Unicode символы, а не управляющие последовательности Python, или, сохраняя все, как и с помощью вспомогательной функции от this answer,

import re 

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) 

вы можете сделать

>>> unicode_unescape('^X.{0,2}[\u2E80-\u9FFF]') 
u'^X.{0,2}[\u2e80-\u9fff]' 

или, в контексте:

f = codecs.open(filename, "r", "utf-8") 
lines = f.read().splitlines() 
filePatterns = FileHelper.fileToList(ignoreFile) 
patternList = [re.compile(unicode_unescape(x), re.IGNORECASE | re.UNICODE) for x in patternList] 

for name in [u'XFlowers for you', u'X桜桜桜桜'] 
    for pattern in patternList: 
     print pattern.search(name); 
+0

PS: Еще один вариант, если вы достаточно смелы, чтобы сделать это (не уверен в значениях безопасности), является 'eval (' u "'+ pattern +'" ') '. – Tomalak

+0

Спасибо, это была большая помощь. Я продолжал находить публикации, говорящие, что все это AOK, поскольку Python делает все правильно, что обычно происходит.Я просто не мог найти средства unescape. – Colin

+1

Интерпретатор Python анализирует строковые литералы Unicode и обращает ссылки '\ uXXXX' в фактические символы Юникода в памяти до запуска программы. Когда вы читаете файл, этот шаг не происходит, естественно. Вместо этого вы просто получаете строки с обратными косыми чертами в них, что, конечно же, не то, что вы хотите. Вот почему работает 'eval()'. – Tomalak

-1

Если вам нужно только английские алфавиты и цифры должны быть согласованы, а не ASCII или другие символы попробовать это регулярное выражение - «\ Ь^Х [\ u0000- \ u007F] + \ б»

Это будет соответствовать только «XFlowers for you»

Надеюсь, это поможет.

Спасибо.

+0

Это противоположность тому, что я пытаюсь сделать. – Colin

+0

Если это так, вы можете использовать символ отрицания (карата). \ b^X [^ \ u0000- \ u007F] + \ b – SasiRSK

+0

Вы действительно должны прочитать вопрос. – Colin