comportamento estranho de parênteses em python regex
-
13-12-2019 - |
Pergunta
Eu estou escrevendo um python regex que olha através de um documento de texto para seqüências de caracteres entre aspas (citação de pilotos de linha aérea gravado a partir de blackboxes).Comecei por tentar escrever uma regex com as seguintes regras:
Devolver o que está entre aspas.
se abre com o único e só voltar se ele fecha com único.
se ela se abre com casal, apenas o retorno se fecha com o casal.
Por exemplo, eu não quero casar com "oi" ou "olá", mas "hi there" e 'oi'.
Eu uso uma página de teste que contém coisas como:
CA "Runway 18, wind 230 degrees, five knots, altimeter 30."
AA "Roger that"
18:24:10 [flap lever moving into detent]
ST: "Some passenger's pushing a switch. May I?"
Então eu decidi começar pelo mais simples:
re.findall('("|\').*?\\1', page)
########## /("|').*?\1/ <-- raw regex I think I'm going for.
Este regex atos muito inesperadamente.
Eu pensei que seria:
- ( " | " ) Correspondência simples OU aspas duplas, salvar como referência de volta /1.
- .*?A correspondência não-ganancioso curinga.
- \1 Coincidir com tudo o que encontra na volta de referência \1 (um passo).
Em vez disso, ele retorna uma matriz de citações, mas nunca qualquer outra coisa.
['"', '"', "'", "'"]
Eu estou realmente confuso porque o equivalente (afaik) regex funciona muito bem no VIM.
\("\|'\).\{-}\1/)
A minha pergunta é esta:
Por que ele retorna apenas o que está dentro de parênteses, como o jogo?Esta é uma falha no meu entendimento de volta referências?Se sim, então por que ele funciona em VIM?
E como faço para escrever o regex eu estou procurando em python?
Obrigado por sua ajuda!
Solução
Leia a documentação. re.findall
retorna os grupos, se houver.Se você quiser toda a partida, você deve agrupar tudo, ou usar re.finditer
.Ver esta pergunta.
Outras dicas
Você não captura qualquer coisa, exceto para as aspas, que é o que o Python está retornando.
Se você adicionar outro grupo, as coisas funcionam muito melhor:
for quote, match in re.finditer(r'("|\')(.*?)\1', page):
print match
Eu prefixado seu literal de cadeia de caracteres com um r
para torná-lo um matérias seqüência de caracteres, o que é útil quando você precisa usar uma tonelada de barras invertidas (\\1
torna-se \1
).
Você precisa pegar tudo com mais um par de parênteses.
re.findall('(("|\').*?\\2)', page)