2016-02-10 5 views
2

Я пытаюсь получить все цифры из следующей строки после слова classes (или его вариации)RegEx: Найти все цифры после определенной строки

Accepted for all the goods and services in classes 16 and 41. 

ожидаемый результат:

16 
41 

У меня есть несколько строк, которые следуют этой схеме, а некоторые другие, такие как:

classes 5 et 30 # expected output 5, 30 
class(es) 32,33 # expected output 32, 33 
class 16  # expected output 5 

Вот что я пытался до сих пор: https://regex101.com/r/eU7dF6/3

(class[\(es\)]*)([and|et|,|\s]*(\d{1,}))+ 

Но я смог получить только последнюю цифру согласованной т.е. 41 в приведенном выше примере.

ответ

1

Я предлагаю захватывая всю подстроку с числами после class или classes/class(es), а затем получить все числа от:

import re 
p = re.compile(r'\bclass(?:\(?es\)?)?(?:\s*(?:and|et|[,\s])?\s*\d+)+') 
test_str = "Accepted for all the goods and services in classes 16 and 41." 
results = [re.findall(r"\d+", x) for x in p.findall(test_str)] 
print([x for l in results for x in l]) 
# => ['16', '41'] 

См IDEONE demo

Как \G конструкта не поддерживается, и вы не можете получить доступ к стеку захватов с помощью модуля Python re, вы не можете использовать свой подход.

Однако вы можете сделать это так, как вы сделали с PyPi regex module.

>>> import regex 
>>> test_str = "Accepted for all the goods and services in classes 16 and 41." 
>>> rx = r'\bclass(?:\(?es\)?)?(?:\s*(?:and|et|[,\s])?\s*(?P<num>\d+))+' 
>>> res = [] 
>>> for x in regex.finditer(rx, test_str): 
     res.extend(x.captures("num")) 
>>> print res 
['16', '41'] 
+0

Спасибо Wiktor, однако то, что вы предложили, также является двукратным подходом, как и ответ, предоставленный 'vks' и, конечно же, Я мог бы использовать этот подход. Но я хотел бы иметь одно регулярное выражение, которое дает мне результаты. – AKS

+0

, но можете ли вы использовать модуль регулярных выражений PyPi? Я сказал, что вы не можете использовать одно регулярное выражение с 're'. –

+0

Использование внешней библиотеки не является проблемой вообще. :) – AKS

1

Вы можете сделать это за 2 шага. Двигатель Regex отслеживает только последнюю группу в непрерывных группах.

x="""Accepted for all the goods and services in classes 16 and 41.""" 
print re.findall(r"\d+",re.findall(r"class[\(es\)]*\s*(\d+(?:(?:and|et|,|\s)*\d+)*)",x)[0]) 

Выход: ['16', '41']

Если вы не хотите string Используйте

print map(ast.literal_eval,re.findall(r"\d+",re.findall(r"class[\(es\)]*\s*(\d+(?:(?:and|et|,|\s)*\d+)*)",x)[0])) 

Выход: [16, 41]

Если вы должны сделать это в одном использовании регулярных выражений regex модуль

import regex 
x="""Accepted for all the goods and services in classes 16 and 41.""" 
print [ast.literal_eval(i) for i in regex.findall(r"class[\(es\)]*|\G(?:and|et|,|\s)*(\d+)",x,regex.VERSION1) if i] 

Выход: [16, 41]

+0

Да! Я мог бы это сделать на самом деле. но мне просто интересно, есть ли чисто регулярное выражение, которое могло бы дать мне то, что мне нужно. – AKS

+0

@AKS check edit..you можете сделать это с помощью модуля 'regex', но его нет в python по умолчанию – vks

+1

@vks Почему вы продолжаете использовать неправильное регулярное выражение? –