Ошибка переопределения регулярного выражения - PullRequest
2 голосов
/ 04 марта 2010

Я использую python и сталкиваюсь с некоторой ошибкой переопределения, я знаю, что это переопределение, но логически невозможно достичь этого, так как его или. Есть ли способ обойти это? Я благодарен за любую помощь заранее

/ python-2.5 / lib / python2.5 / re.py ", строка 233, в _compile поднять ошибку, v # неверное выражение sre_constants.error: переопределение имени группы 'id' как группы 9; была группа 6


import re

DOB_RE =  "(^|;)DOB +(?P<dob>\d{2}-\d{2}-\d{4})"
ID_RE =   "(^|;)ID +(?P<id>[A-Z0-9]{12})"
INFO_RE = "- (?P<info>.*)"

PERSON_RE = "((" + DOB_RE + ".*" + ID_RE +  ")|(" + \
                   ID_RE  + ".*" + DOB_RE + ")|(" + \
                   DOB_RE + "|" + ID_RE + ")).*(" + INFO_RE + ")*"

PARSER = re.compile(PERSON_RE)

samplestr1 = garbage;DOB 10-10-2010;more garbage\nID PARI12345678;more garbage
samplestr2 = garbage;ID PARI12345678;more garbage\nDOB 10-10-2010;more garbage
samplestr3 = garbage;DOB 10-10-2010
samplestr4 = garbage;ID PARI12345678;more garbage- I am cool

Ответы [ 3 ]

2 голосов
/ 04 марта 2010

Первоначально я собирался опубликовать пример pyparsing с использованием класса Each (который выбирает выражения, которые могут быть в любом порядке), но затем я увидел, что был смешанный мусор, поэтому поиск по вашей строке с использованием searchString казалсялучше подойдет.Это заинтриговало меня, потому что searchString возвращает последовательность ParseResults, по одному на каждое совпадение (включая любые соответствующие именованные результаты).Поэтому я подумал: «Что, если я объединю возвращенные результаты ParseResults с использованием суммы - что за хак!», Эээ, «Как оригинально!»Итак, вот никогда ранее не замеченный взлом pyparsing:

from pyparsing import *
# define the separate expressions to be matched, with results names
dob_ref = "DOB" + Regex(r"\d{2}-\d{2}-\d{4}")("dob")
id_ref = "ID" + Word(alphanums,exact=12)("id")
info_ref = "-" + restOfLine("info")

# create an overall expression
person_data = dob_ref | id_ref | info_ref

for test in (samplestr1,samplestr2,samplestr3,samplestr4,):
    # retrieve a list of separate matches
    separate_results = person_data.searchString(test)

    # combine the results using sum
    # (NO ONE HAS EVER DONE THIS BEFORE!)
    person = sum(separate_results, ParseResults([]))

    # now we have a uber-ParseResults object!
    print person.id
    print person.dump()
    print

Предоставление этого вывода:

PARI12345678
['DOB', '10-10-2010', 'ID', 'PARI12345678']
- dob: 10-10-2010
- id: PARI12345678

PARI12345678
['ID', 'PARI12345678', 'DOB', '10-10-2010']
- dob: 10-10-2010
- id: PARI12345678


['DOB', '10-10-2010']
- dob: 10-10-2010

PARI12345678
['ID', 'PARI12345678', '-', ' I am cool']
- id: PARI12345678
- info:  I am cool

Но я также говорю на регулярное выражение.Вот аналогичный подход с использованием re.

import re

# define each individual re, with group names
dobRE = r"DOB +(?P<dob>\d{2}-\d{2}-\d{4})"
idRE = r"ID +(?P<id>[A-Z0-9]{12})"
infoRE = r"- (?P<info>.*)"

# one re to rule them all
person_dataRE = re.compile('|'.join([dobRE, idRE, infoRE]))

# using findall with person_dataRE will return a 3-tuple, so let's create 
# a tuple-merger
merge = lambda a,b : tuple(aa or bb for aa,bb in zip(a,b))

# let's create a Person class to collect the different data bits 
# (or if you are running Py2.6, use a namedtuple
class Person:
    def __init__(self,*args):
        self.dob, self.id, self.info = args
    def __str__(self):
        return "- id: %s\n- dob: %s\n- info: %s" % (self.id, self.dob, self.info)

for test in (samplestr1,samplestr2,samplestr3,samplestr4,):
    # could have used reduce here, but let's err on the side of explicity
    persontuple = ('','','')
    for data in person_dataRE.findall(test):
        persontuple = merge(persontuple,data)

    # make a person
    person = Person(*persontuple)

    # print out the collected results
    print person.id
    print person
    print

С этим выводом:

PARI12345678
- id: PARI12345678
- dob: 10-10-2010
- info: 

PARI12345678
- id: PARI12345678
- dob: 10-10-2010
- info: 


- id: 
- dob: 10-10-2010
- info: 

PARI12345678
- id: PARI12345678
- dob: 
- info: I am cool
2 голосов
/ 04 марта 2010

Синтаксис регулярного выражения просто не допускает множественных вхождений групп с одинаковыми именами - группы, которые не «достигнуты», определяются как «пустые» (нет) в совпадении.

Таким образом, вы должны изменить эти имена, например на dob0, dob1, dob2 и id0, id1, id2 (тогда вы можете легко «свернуть» эти наборы ключей, чтобы получить нужный вам диктат после того, как у вас есть словарь групп из матч).

Например, сделать DOB_RE функцией вместо константы, скажем:

def DOB_RE(i): return "(^|;)DOB +(?P<dob%s>\d{2}-\d{2}-\d{4})" % i

и аналогично для остальных, и измените три вхождения DOB_RE в выражении, где вы вычисляете PERSON_RE на DOB_RE(0), DOB_RE(1) и т. Д. (И аналогично для остальных).

1 голос
/ 04 марта 2010

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

>>> strs=[
... "garbage;DOB 10-10-2010;more garbage\nID PARI12345678;more garbage",
... "garbage;ID PARI12345678;more garbage\nDOB 10-10-2010;more garbage",
... "garbage;DOB 10-10-2010",
... "garbage;ID PARI12345678;more garbage- I am cool"]
>>> import re
>>> 
>>> DOB_RE =  "(^|;|\n)DOB +(?P<dob>\d{2}-\d{2}-\d{4})"
>>> ID_RE =   "(^|;|\n)ID +(?P<id>[A-Z0-9]{12})"
>>> INFO_RE = "(- (?P<info>.*))?"
>>> 
>>> REGEX = map(re.compile,[DOB_RE + ".*" + ID_RE + "[^-]*" + INFO_RE,
...                         ID_RE + ".*" + DOB_RE + "[^-]*" + INFO_RE,
...                         DOB_RE + "[^-]*" + INFO_RE,
...                         ID_RE + "[^-]*" + INFO_RE])
>>> 
>>> def get_person(s):
...     for regex in REGEX:
...         res = re.search(regex,s)
...         if res:
...             return res.groupdict()
... 
>>> for s in strs:
...     print get_person(s)
... 
{'dob': '10-10-2010', 'info': None, 'id': 'PARI12345678'}
{'dob': '10-10-2010', 'info': None, 'id': 'PARI12345678'}
{'dob': '10-10-2010', 'info': None}
{'info': 'I am cool', 'id': 'PARI12345678'}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...