Quero processar todas as linhas do meu arquivo de log e extrair o IP
endereço se a linha corresponder ao meu padrão. Existem vários tipos diferentes de mensagens, no exemplo abaixo, estou usando p1 and
p2`.
Eu podia ler o arquivo linha por linha e para cada linha corresponder a cada padrão. Mas como pode haver muitos outros padrões, eu gostaria de fazê-lo da maneira mais eficiente possível. Eu esperava compilar esses padrões em um objeto e fazer a correspondência apenas uma vez para cada linha:
import re
IP = r'(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
p1 = 'Registration from' + IP + '- Wrong password'
p2 = 'Call from' + IP + 'rejected because extension not found'
c = re.compile(r'(?:' + p1 + '|' + p2 + ')')
for line in sys.stdin:
match = re.search(c, line)
if match:
print(match['ip'])
mas o código acima não funciona, ele reclama que ip
é usado duas vezes.
Qual é a maneira mais elegante de alcançar meu objetivo?
EDITAR:
Modifiquei meu código com base nas respostas de @Dev Khadka.
Mas ainda estou lutando para lidar adequadamente com as várias ip
correspondências. O código abaixo imprime todos os IPs correspondentes a p1:
for line in sys.stdin:
match = c.search(line)
if match:
print(match['ip1'])
Mas algumas linhas não correspondem p1
. Eles combinamp2
. ou seja, eu recebo:
1.2.3.4
None
2.3.4.5
...
Como faço para imprimir o ip de correspondência, quando eu não sei wheter que era p1
, p2
...? Tudo o que eu quero é o IP. Eu não ligo para qual padrão ele combina.
fonte
Respostas:
Você pode considerar instalar o
regex
módulo excelente , que suporta muitos recursos avançados de regex, incluindo grupos de redefinição de ramificação , projetados para resolver exatamente o problema descrito nesta pergunta. Os grupos de redefinição de ramificação são indicados por(?|...)
. Todos os grupos de captura das mesmas posições ou nomes em diferentes padrões alternativos em um grupo de redefinição de ramificação compartilham os mesmos grupos de captura para saída.Observe que, no exemplo abaixo, o grupo de captura correspondente se torna o grupo de captura nomeado, para que você não precise iterar sobre vários grupos procurando um grupo não vazio:
Demonstração: https://repl.it/@blhsing/RegularEmbellishedBugs
fonte
por que você não verifica qual regex corresponde?
ou algo como:
ou mesmo
fonte
match[i]
no loop for?if match[name] is not None:
IndexError: no such group
name in match
vezisso é porque você está usando o mesmo nome de grupo para dois grupos
tente isso, isso dará nomes de grupo ip1 e ip2
fonte
Grupos de captura nomeados devem ter nomes distintos, mas como todos os seus grupos de captura devem capturar o mesmo padrão, é melhor não usar grupos de captura nomeados nesse caso, mas simplesmente usar grupos de captura regulares e iterar pelos grupos do objeto de correspondência para imprimir o primeiro grupo que não está vazio:
Demonstração: https://repl.it/@blhsing/UnevenCheerfulLight
fonte