Python RE — разные соответствия для finditer и findall

вот код:

>>> p = re.compile(r'\S+ (\[CC\] )+\S+')
>>> s1 = 'always look [CC] on the bright side'
>>> s2 = 'always look [CC] [CC] on the bright side'
>>> s3 = 'always look [CC] on the [CC] bright side'
>>> m1 = p.search(s1)
>>> m1.group()
'look [CC] on'
>>> p.findall(s1)
['[CC] ']
>>> itr = p.finditer(s1)
>>> for i in itr:
...     i.group()
... 
'look [CC] on'

Очевидно, это более актуально для поиска всех совпадений в s3, в котором findall возвращает: ['[CC] ', '[CC] '], так как кажется, что findall соответствует только внутренней группе в p, а finditer соответствует всему шаблону.

Почему это происходит?

(Я определил p так же, как и для того, чтобы разрешить захват шаблонов, содержащих последовательности [CC], такие как «смотреть [CC] [CC] дальше» в s2).

Спасибо


person ScienceFriction    schedule 28.09.2010    source источник


Ответы (1)


i.group() возвращает полное совпадение, включая непробельные символы до и после вашей группы. Чтобы получить тот же результат, что и в вашем примере findall, используйте i.group(1)

http://docs.python.org/library/re.html#re.MatchObject.group

In [4]: for i in p.finditer(s1):
...:     i.group(1)
...:     
...:     
Out[4]: '[CC] '
person Benjamin Wohlwend    schedule 28.09.2010
comment
Я не уверен, что понимаю. findall() возвращает список совпадающих строк. Как я могу использовать группу (1) на своем выходе? - person ScienceFriction; 28.09.2010
comment
Нет, вы используете группу для элементов в итераторе, возвращенном из p.finditer(s1). Я добавил пример в свой ответ. - person Benjamin Wohlwend; 28.09.2010
comment
ах, спасибо. Я знаю, как использовать группу (1) с итератором. дело в том, что я хочу получить тот же результат, что и в finditer - я хочу получить весь шаблон. Я не понимаю, почему findall не возвращает полный шаблон. - person ScienceFriction; 28.09.2010
comment
Это задокументированное поведение: если в шаблоне присутствует одна или несколько групп, вернуть список групп, docs.python.org/library/re.html#re.findall - person Benjamin Wohlwend; 28.09.2010
comment
Спасибо. Я этого не заметил. В основном это означает, что я должен определить весь шаблон как внешнюю группу: p = re.compile(r'(\S+ (\[CC\] )+\S+)') и затем использовать только первый элемент в каждом кортеже в возвращаемом списке кортежей. Или просто используйте finditer() :) - person ScienceFriction; 28.09.2010