Как захватить строки с помощью * или? с группами в регулярных выражениях Python
У меня есть str1 и str2 ниже, и я хочу использовать только одно регулярное выражение, которое будет соответствовать обоим. В случае str1 я также хочу иметь возможность захватывать количество портов QSFP
>>> str1='''4 48 48-port and 6 QSFP 10GigE Linecard 7548S-LC'''
>>> str2='''4 48 48-port 10GigE Linecard 7548S-LC'''
>>>
Я хочу быть в состоянии захватить числа "4", "48", "6" (если присутствует) и "7548". Но я не могу захватить "6" с помощью "?" метасимволом.
Когда я не использую метасимвол, захват работает для str1, но тогда я могу использовать это регулярное выражение, потому что он не будет работать для str2:
>>> re.search(r'^(\d+)\s+(\d+)\s+.*(?:(\d+)\s+QSFP).*\s+(\d+)S-LC', str1, re.I|re.M).group(3)
'6'
>>>
Это работает, даже когда я использую "+", чтобы указать одно вхождение, но опять же, это не будет работать для str2:
>>> re.search(r'^(\d+)\s+(\d+)\s+.*(?:(\d+)\s+QSFP)+.*\s+(\d+)S-LC', str1, re.I|re.M).group(3)
'6'
>>>
Когда я использую "?" чтобы соответствовать 0 или 1 вхождению, перехват не выполняется даже для str1:
>>> re.search(r'^(\d+)\s+(\d+)\s+.*(?:(\d+)\s+QSFP)?.*\s+(\d+)S-LC', str1, re.I|re.M).group(3)
>>>
4 ответа
Моя интерпретация проблемы заключалась в том, что OP хотел регулярное выражение, которое будет соответствовать обеим строкам и возвращать число в.group(1), если оно существует (как в str1). Я полагаю, что проблема заключалась в том, что он / она не смогли ни захватить "6" на стр.1, но и сопоставить стр2.
Я получил это из некоторых быстрых проб и ошибок:
>>> str1='''4 48 48-port and 6 QSFP 10GigE Linecard 7548S-LC'''
>>> str2='''4 48 48-port 10GigE Linecard 7548S-LC'''
>>> re.search(r'^4\s+48\s+.*(?:(\d+)\s+QSFP)|.*-LC', str1, re.I|re.M).group(1)
'6'
>>> re.search(r'^4\s+48\s+.*(?:(\d+)\s+QSFP)|.*-LC', str2, re.I|re.M).group(1)
>>> # no error returned, implying a match was found.
Разница в том, что я "или" не захватывая паренов с.*
К сожалению, это делает регулярное выражение еще более трудным для понимания, но, возможно, это сработает для вас.
(отредактировано для полноты)
Я хочу быть в состоянии захватить числа "4", "48", "6" (если присутствует) и "7548". Но я не могу захватить "6" с помощью "?" метасимволом.
Вы можете упростить свою жизнь, если будете избегать регулярных выражений, поскольку ваш запрос очень прост.
str1='''4 48 48-port and 6 QSFP 10GigE Linecard 7548S-LC'''
str2='''4 48 48-port 10GigE Linecard 7548S-LC'''
lines = [str1,str2]
nums = []
for l in lines:
r = []
bits = l.split()
last_num = bits.pop()[:-4]
_ = [r.append(i) for i in bits if i.isdigit()]
r.append(last_num)
nums.append(r)
>>> nums
[['4', '48', '6', '7548'], ['4', '48', '7548']]
Я не уверен, что именно ваше требование.
Это что-то вроде этого:
>>> str1 = "hello 12 world"
>>> str2 = "hello world"
>>> obj = re.search(r'(\d+)',str1)
>>> obj.group(0)
'12'
Сейчас регистрируюсь str2
который не содержит никакого десятичного значения.
>>> obj = re.search(r'(\d+)',str2)
>>> if obj is not None:
... print obj.group(0)
... else:
... print "not found"
...
not found
>>>
Я думаю, что проблема в том, что .*
съедает бит QSFP, и из-за ?
у него нет стимула когда-либо отступать. Изменение .*
не жадным .*?
(удивительно - мне по крайней мере) не помогло. Перемещение .*
однако внутри группы без захвата действительно помогает:
>>> re.match(r'^4\s+48\s+(?:.*(\d+)\s+QSFP)?.*-LC', str1, re.I|re.M).group(1)
'6'
>>> re.match(r'^4\s+48\s+(?:.*(\d+)\s+QSFP)?.*-LC', str2, re.I|re.M).group(1)
>>>