python3: trích xuất địa chỉ IP từ mẫu đã biên dịch


8

Tôi muốn xử lý mọi dòng trong tệp nhật ký của mình và trích xuất IPđịa chỉ nếu dòng khớp với mẫu của tôi. Có một số loại tin nhắn khác nhau, ví dụ bên dưới tôi đang sử dụng p1 andp2`.

Tôi có thể đọc từng dòng tệp và cho từng dòng khớp với từng mẫu. Nhưng vì có thể có nhiều mẫu hơn, tôi muốn làm nó hiệu quả nhất có thể. Tôi đã hy vọng biên dịch các mẫu thos thành một đối tượng và chỉ thực hiện khớp một lần cho mỗi dòng:

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'])

nhưng đoạn mã trên không hoạt động, nó phàn nàn rằng ipđược sử dụng hai lần.

Cách thanh lịch nhất để đạt được mục tiêu của tôi là gì?

BIÊN TẬP:

Tôi đã sửa đổi mã của mình dựa trên câu trả lời từ @Dev Khadka.

Nhưng tôi vẫn đang vật lộn với cách xử lý đúng nhiều iptrận đấu. Mã dưới đây in tất cả các IP khớp với p1:

for line in sys.stdin:
    match = c.search(line)
    if match:
        print(match['ip1'])

Nhưng một số dòng không khớp p1. Họ hợp nhau p2. tức là tôi nhận được:

1.2.3.4
None
2.3.4.5
...

Làm thế nào để in các ip phù hợp, khi tôi không biết wheter nó là p1, p2...? Tất cả tôi muốn là IP. Tôi không quan tâm mẫu nào phù hợp.


1
Bạn nên cung cấp dữ liệu thử nghiệm của bạn.
Eyllanesc

Câu trả lời:


4

Bạn có thể xem xét việc cài đặt regexmô-đun xuất sắc , hỗ trợ nhiều tính năng regex nâng cao, bao gồm các nhóm đặt lại nhánh , được thiết kế để giải quyết chính xác vấn đề bạn nêu trong câu hỏi này. Các nhóm thiết lập lại chi nhánh được ký hiệu bởi (?|...). Tất cả các nhóm chụp có cùng vị trí hoặc tên trong các mẫu thay thế khác nhau trong nhóm thiết lập lại nhánh chia sẻ cùng một nhóm chụp cho đầu ra.

Lưu ý rằng trong ví dụ bên dưới, nhóm chụp phù hợp sẽ trở thành nhóm chụp có tên, do đó bạn không cần phải lặp lại qua nhiều nhóm tìm kiếm một nhóm không trống:

import regex

ip_pattern = r'(?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
patterns = [
    'Registration from {ip} - Wrong password',
    'Call from {ip} rejected because extension not found'
]
pattern = regex.compile('(?|%s)' % '|'.join(patterns).format(ip=ip_pattern))
for line in sys.stdin:
    match = regex.search(pattern, line)
    if match:
        print(match['ip'])

Bản trình diễn: https://repl.it/@blhsing/RegularEmbellishedBugs


1
Đây là hoàn hảo! Cảm ơn bạn.
Martin Vegter

2

Tại sao bạn không kiểm tra regex nào khớp?

if 'ip1' in match :
    print match['ip1']
if 'ip2' in match :
    print match['ip2']

hoặc đại loại như:

names = [ 'ip1', 'ip2', 'ip3' ]
for n in names :
    if n in match :
        print match[n]

hoặc thậm chí

num = 1000   # can easily handle millions of patterns =)
for i in range(num) :
    name = 'ip%d' % i
    if name in match :
        print match[name]

Nhưng nếu tôi có 100 mẫu thì sao? Tôi có thể làm điều này trong một vòng lặp? Tôi có thể lặp lại match[i]trong vòng lặp for không?
Martin Vegter

@MartinVegter xem ở trên
lenik

@MartinVegter có thể xử lý hàng triệu mẫu dễ dàng =)
lenik

Tôi gặp lỗi:if match[name] is not None: IndexError: no such group
Martin Vegter

@MartinVegter thử sử dụng name in matchthay thế
lenik

1

đó là bởi vì bạn đang sử dụng cùng một tên nhóm cho hai nhóm

Hãy thử điều này, nó sẽ cho tên nhóm ip1 và ip2

import re

IP = r'(?P<ip%d>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'

p1 = 'Registration from' + IP%1 + '- Wrong password' 
p2 = 'Call from' + IP%2 + 'rejected because extension not found'

c = re.compile(r'(?:' + p1 + '|' + p2 + ')')

1

Các nhóm chụp được đặt tên phải có tên riêng biệt, nhưng vì tất cả các nhóm chụp của bạn đều có nghĩa là bắt cùng một mẫu, tốt hơn hết là không sử dụng các nhóm chụp có tên trong trường hợp này mà thay vào đó chỉ cần sử dụng các nhóm chụp thông thường và lặp qua các nhóm từ đối tượng khớp để in nhóm đầu tiên không trống:

ip_pattern = r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
patterns = [
    'Registration from {ip} - Wrong password',
    'Call from {ip} rejected because extension not found'
]
pattern = re.compile('|'.join(patterns).format(ip=ip_pattern))
for line in sys.stdin:
    match = re.search(pattern, line)
    if match:
        print(next(filter(None, match.groups())))

Bản trình diễn: https://repl.it/@blhsing/UnevenCheerfulLight

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.