Регулярное выражение Python с опережением символов, отличных от ASCII

У меня есть большая часть этого регулярного выражения, однако у меня проблемы с просмотром вперед. Я хочу разделить строку на почтовый индекс, за которым следуют две строки или два числа. Цифры могут быть в виде:

1
1.5
1.55
11.55

Текст для среднего бита может быть «Нет минимума», а текст для третьего бита может быть только «Свободным».

E.g.

"YO1£ 10Free" ==> YO1; 10; Бесплатно

or

"yo1£ 8£ 0.5" ==> yo1; 8; 0.5

or

"yo1Нет минимума £ 0,75" ==> yo1; Нет минимума; 0,75

Я сделал первый бит с этим:

string = "YO1£ 10Free"
patternPostCode = re.compile("[a-zA-Z]{1,2}[0-9][a-zA-Z0-9]?")
postCode = re.findall(string,patternPostCode)

Цифры в строке находятся:

patternCost = re.compile(r"(?<=\xa3 )([0-9]|  
[0-9][0-9]|  
[0-9]?[0-9]?.[0-9]|
[0-9]?[0-9]?.[0-9][0-9])")

У меня возникли трудности с добавлением «или текст равен «Нет минимума»» в поиск по шаблону. Я также не могу включить просмотр вперед Â. Добавление этого в конце не работает:

(?<=\xc2)

Любая помощь будет оценена по достоинству.


person eamon1234    schedule 04.12.2012    source источник


Ответы (1)


Я придумал это на Python 2.7:

# -*- coding: utf-8 -*-
import re

raw_string = "YO1£ 10.01Free"
string = raw_string.decode('utf-8')
patternPostCode = re.compile(u"^(\w{3}.*)\s+(\d+\.?\d*)(\w+)$",flags=re.UNICODE)
postCode = patternPostCode.findall(string)

print postCode
print u'; '.join(postCode[0])

Это возвращает:

[(u'YO1\xc2\xa3', u'10.01', u'Free')]
YO1£; 10.01; Free

Во-первых, необработанная строка, которую я скопировал из SO, оказалась строкой байтов, мне пришлось декодировать ее в unicode (см. строка байтов и строка юникода. Python). Я думаю, что у вас могут быть ошибки кодирования Unicode в целом - символ Â является классическим признаком этого.

Затем я сделал ваше регулярное выражение удобным для юникода с флагом re.UNICODE. Это означает, что вы можете использовать \w для обозначения «буквенно-цифровых» и \d для обозначения «цифр» в удобном для Unicode виде.

http://docs.python.org/2/library/re.html#module-re

Поскольку регулярные выражения часто ошибочно принимают за шум строки, давайте распаковываем для вас:

u"^(\w{3}.*)\s+(\d+\.?\d*)(\w+)$"
  • ^ = начало строки
  • (\w{3}.*) = соответствует ровно трем буквенно-цифровым символам (\w{3}), за которыми следует что-либо (.*) и сгруппировано (это скобки вокруг всего этого). Я вообще не люблю .*, но надо было прихватить барахло ££. Если вы не хотите этого, переместите его за скобки.
  • \s+ - хотя бы один пробел. мы выбросим это
  • (\d+.?\d*) - соответствует одной или нескольким цифрам, за которыми следует необязательная точка, за которой может следовать одна или несколько цифр. Это будет соответствовать 10, 10., 10.0, 10.0000 и так далее.
  • (\w+) - один или несколько буквенно-цифровых символов
  • $ - соответствует концу строки

Это, конечно, не самое красивое регулярное выражение, которое я когда-либо писал, но, надеюсь, этого достаточно, чтобы вы начали.

person Rachel Sanders    schedule 04.12.2012
comment
Спасибо Рейчел, это очень помогает. Регулярные выражения довольно пугающие, так что спасибо за объяснение! Приветствую совет по юникоду, который ломал мне голову! - person eamon1234; 05.12.2012
comment
Ву! Я рад, что это помогло вам. Юникод — заноза в заднице в Python 2, это видео о Pycon помогло мне начать разбираться с ним: youtube .com/watch?v=sgHbC6udIqc - person Rachel Sanders; 05.12.2012