2015-07-19 4 views
2

Привет Я новичок в Python и RegEx. Я экспериментирую с обоими и пытаюсь получить одно регулярное выражение для извлечения данных от пользователя, но я ожидаю разные входы, учитывая опечатки и т. Д. Поэтому в следующем коде я произвольно выбираю какой-то тип строк, который я ожидаю от пользователя дать вам пример того, как они могут вводить данные. Меня интересует только число, которое приходит до или после USD. Например:Эффективное регулярное выражение для нескольких строк с символами и цифрами

ran = random.randint(1, 7) 
print str(ran) 
if ran == 1: 
    examplestring = "This item costs 20 USD contact 9999999" 
elif ran == 2: 
    examplestring = "This item costs USD 20" 
elif ran == 3: 
    examplestring = "This item costs 20 U.S.D" 
elif ran == 4: 
    examplestring = "This item costs 20 usd" 
elif ran == 5: 
    examplestring = "This item costs 20 Usd call to buy : 954545577" 
elif ran == 6: 
    examplestring = "This item costs 20USD" 
elif ran == 7: 
    examplestring = "This item costs usd20" 

regex = re.compile(r'\busd|\bu.s.d\b|\bu.s.d.\b', re.I) 
examplestring = regex.sub("USD", examplestring) 
costs = re.findall(r'\d+.\bUSD\b|\bUSD\b.\d+|\d+USD\b|\bUSD\d+', examplestring) 
cost = "".join(str(n) for n in costs[0]) 
cost = ''.join(x for x in cost if x.isdigit()) 
print cost + " USD" 

Используя эти регулярные выражения, я могу получить деталь, которую я хочу, которая составляет «20 долларов США». Мой вопрос в том, правильно ли я делаю это, и если можно сделать код лучше?

+0

Вы можете сделать все это с одним регулярным выражением: '(: (<= USD | USD) \ S * (\ d +)?) | (?: \ d + \ s * (? = USD | usd | Usd | USD)), но иногда это не очень хороший способ сделать это из-за сложности регулярного выражения. См. Объяснение [здесь] (https://regex101.com/r/mH0cC8/1) о том, как это работает. – RedX

ответ

1

способ сделать это:

regex = re.compile(r'\b(?=[0-9U])(?:[0-9]+\s*U\.?S\.?D|U\.?S\.?D\s*[0-9]+)\b', re.I) 

result = [x.strip(' USD.usd') for x in regex.findall(yourstring)] 

шаблонов детали:

\b   # word boundary 
(?=[0-9U]) # only here to quickly discard word-boundaries not followed 
      # by a digit or the letter U without to test the two branches 
      # of the following alternation. You can remove it if you want. 

(?: 
    [0-9]+\s*U\.?S\.?D # USD after 
    |     # OR 
    U\.?S\.?D\s*[0-9]+ # USD before 
) 
\b 

Обратите внимание, что пробелы и точки не являются обязательными для двух ветвей.

Затем «USD» часть результата удаляется простой полосой. это более удобно (и, вероятно, быстрее), чем пытаться исключить доллар США из результата матча с помощью поисковых запросов.

+0

Это работает отлично, спасибо вам большое, но что делать, если пользователь делает опечатку и дает что-то вроде u, s, d вместо u.s.d, как включить запятую? –

+0

@Cheth_K: невозможно обрабатывать все возможные опечатки юниверса, но для вашего конкретного вопроса замените '\ .' на' [,.] 'И добавьте запятую в список символов полосы. –

+0

Удивительно большое вам спасибо! –

0

В качестве общего решения [0-9]+ будет извлекать только сумму, не считая окружающего ее текста. Он фокусируется на том, что вам нужно извлечь, а не на том, что можно игнорировать.

+0

Хорошо, я отредактировал его, в первый раз, когда я не опубликовал его правильно. Пользователь также может предоставить другие данные, такие как номера телефонов. Поэтому я предположил, что число, которое мне нужно, всегда приходит либо сразу после, либо раньше usd. –

+0

Почему downvote? OP изменил спецификации после моего ответа, до этого мой ответ был действительным. – user1016274

+0

Я не знаю, кто отказался от этого, wasnt me –

0

Вы можете использовать одно регулярное выражение с группами для непосредственного извлечения значений. Например, «(\ d +) * u \.? S \.? D \.? \ U \.? S \.? D \.? * (\ D +)" может использоваться для поиска ваших строк (с игнорировать), а затем, если вы получите совпадение, ваши затраты будут либо в группе 1, либо в группе 2, в зависимости от выбранного варианта.

1

Я рекомендую Regex101 для получения дополнительной информации и объяснения данного регулярного выражения. Особенно вы должны обратить внимание на группы (например, (\d+)), потому что я думаю, что это то, что вам нужно для правильного извлечения значения.

Подстановка, а затем поиск в этой замененной строке как-то беспорядочно, на мой взгляд.

import re 
lines = """This item costs 20 USD 
This item costs USD 20 
This item costs 20 U.S.D 
This item costs 20 usd 
This item costs 20 Usd 
This item costs 20USD 
This item costs usd20""" 

# as you can see there are two groups with the price 
pattern = re.compile(r"u\.?s\.?d\s*(\d+)|(\d+)\s*u\.?s\.?d", re.I) 
# one of the groups must have matched, so I take the non-empty one using `or`operator 
print ["{} USD".format(fst or sec) for fst, sec in pattern.findall(lines)] 

Out:

['20 USD', '20 USD', '20 USD', '20 USD', '20 USD', '20 USD', '20 USD'] 
+0

Использование логического теста - очень хорошая идея. –

Смежные вопросы