/ / Python3: as correspondências do subgrupo não funcionam para OR '|' expressões regulares unidas - regex, python-3.x

Python3: combinações de subgrupos não funcionando para OR '|' expressões regulares unidas - regex, python-3.x

Estou tentando analisar algumas linhas de um arquivo csv para extrair uma série de dígitos. Existem dois formatos possíveis, apenas os dígitos ou os dígitos incorporados em um código mais longo.

Aqui está um exemplo de código do que estou fazendo e do que está errado:

# regex works
>>> re.search("^(d+)$", "5755").group(0, 1)
("5755", "5755")

# regex works with capturing group inside non-capturing group
>>> re.search("(?:^(d+)$)", "5755").group(0, 1)
("5755", "5755")

# regex does not work as second of two non-capturing groups
>>> re.search("(?:$SK-*(d+)[-K])|(?:^(d+)$)", "5755").group(0, 1)
("5755", None)

# the other regex of the pair works
>>> re.search("(?:$SK-*(d+)[-K])|(?:^(d+)$)", "11$SK-2301-K13").group(0, 1)
("$SK-2301-", "2301")

# the regex works as the first of two non-capturing groups
>>> re.search("(?:^(d+)$)|(?:$SK-*(d+)[-K])", "5755").group(0, 1)
("5755", "5755")

Como você pode ver, a expressão regular funciona bempor si só, ou envolto em um (? ...), mas quando combinado com outra regex, o grupo do segundo dos dois regex "s deixa de funcionar, mesmo que a pesquisa retorne um objeto de correspondência. No entanto, se eu trocar a ordem das regexs que são canalizadas juntas, a primeira ainda funcionará independentemente de qual regex for.

Para ser claro, quando eu combino duas regexs de trabalho em conjunto com um pipe ("|"), os grupos do primeiro funcionam, mas os do segundo não.

Por que isso está acontecendo? Como posso consertar isso?

Respostas:

1 para resposta № 1

A causa do problema é que o entendimento intuitivo de como os subgrupos funcionam não é como eles funcionam na prática.

Vou expandir o que dois comentários diferentes sobre sua pergunta apontam corretamente. Os subgrupos não são numerados à medida que são capturados, mas são fixos na criação / análise da regex. Por exemplo:

re.search("match:(foo)","match:foo").group(1)

Será

("foo")

Como o primeiro grupo de captura é (foo). similarmente

re.search("match:(foo)(bar)","match:foobar").group(1,2)

Será

("foo","bar")

Como o primeiro e o segundo grupos de captura são (foo) e (bar) e cada um deles correspondeu e foi capturado.

Em um padrão como

match:(?:(foo)|(bar))

(foo) e (bar) ainda são o primeiro e o segundo grupos de captura, mesmo que apenas um deles possa capturar graças ao OR |.

re.search("match:(?:(foo)|(bar))","match:foo").group(1,2)
re.search("match:(?:(foo)|(bar))","match:bar").group(1,2)

Saída

("foo", None)
(None, "bar")

Portanto, você precisará adicionar alguma lógica ao seu código para verificar qual dos grupos de captura possui conteúdo e retornar esse.