регулярное выражение в Python: группы и | - PullRequest
1 голос
/ 25 августа 2011

Я не могу найти, как поступить с регулярным выражением, вот пример:

string = "red\\/banana 36    monkey\\/apple 14   red\\/apple 23  red\\/horse 56  bull\\/red 67  monkey\\/red 45    bull\\/shark 89"

Я хочу сделать одиночное регулярное выражение с re.match.group (), которая будет учитывать только такие, как red / xxxx и xxxx / red, и группировать только имена xxxx , а не пары:

Я хочу сделать:

print(match.group("beginningwithred") + " " + match.group("number")

и получите:

banana 36
apple 23
horse 56

, затем выполните:

print(match.group("endingwithred") + " " + match.group("number")

и получите:

bull 67
monkey 45

мой текущий код выглядит так:

iterator = regex.finditer(string)
for match in iterator:
    regex = re.compile('red\\\\\\\\/(?P<beginningwithred>banana|apple|horse)|(?P<endingwithred>bull|monkey)\\\\\\\\/red (?P<number>\d\d)')

но это не работает, я не могу использовать |между группами и python HOWTO не помогает .. Я пробовал с {} тоже, включая целые два выражения, но это тоже не работает.Это не должно быть действительно сложно, но я не могу выяснить, в чем дело.

Ответы [ 2 ]

3 голосов
/ 25 августа 2011

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

(?:foo|bar|baz)

, что позволяет использовать | без создания «реальной» группы.


обновление почему это не помогает?не так ли?

>>> s="red\\/banana 36    monkey\\/apple 14   red\\/apple 23  red\\/horse 56  bull\\/red 67  monkey\\/red 45    bull\\/shark 89"
>>> r = re.compile(r'(?:red\\/(?P<begin>\w+)|(?P<end>\w+)\\/red)\s+(?P<number>\d+)')
>>> for m in r.finditer(s):
...     print(m.groups())

('banana', None, '36')
('apple', None, '23')
('horse', None, '56')
(None, 'bull', '67')
(None, 'monkey', '45')

update2

, если вы просто хотите распечатать значения, отличные от None, вы можете сделать что-то вроде:

  >>> for m in r.finditer(s):
  ...     print(','.join(g for g in m.groups() if g is not None))
1 голос
/ 25 августа 2011

Я уверен, что невозможно найти extra_terrestial_regex , совпадающий со всеми случаями, с «красным» в первой позиции и с «красным» во второй позиции, но так:

for mat in extra_terrestial_regex.finditer(s):
    print mat.group("beginningwithred") + " " + match.group("number")

выберет только совпадения с «красным» на первой позиции и пропустит остальные.

.

Это не регулярное выражение, которое может получить такой результат,это только функция;следующий выполняет то, что вы хотите?

import re

s = ('red\\/banana 36    monkey\\/apple 14  '
     'red\\/apple 23  red\\/horse 56  bull\\/red 67 '
     'monkey\\/red 45    bull\\/shark 89')


def gen(s,what,word):
    if what=='beginning':
        regx = re.compile(r'%s\\/([^ ]+) (\d+)' % word)
    elif what=='ending':
        regx = re.compile(r'([^ ]+)\\/%s (\d+)' % word)
    else:
        regx = re.compile('(\A).*(\Z)')
    for mat in regx.finditer(s):
        yield mat.groups()


print '\n'.join('%s %s' % x for x in gen(s,'beginning','red'))
print '----------------'
print '\n'.join('%s %s' % x for x in gen(s,'ending','red'))
print '----------------'
print '\n'.join('%s %s' % x for x in gen(s,'ZOU','red'))
print '----------------'
print '\n'.join('%s %s' % x for x in gen(s,'ending','apple'))

результат

banana 36
apple 23
horse 56
----------------
bull 67
monkey 45
----------------

----------------
monkey 14
red 23
...