Разбор файла организован по определенному шаблону

f является файлом и показан ниже:

+++++192.168.1.1+++++
Port Number: 80
......
product: Apache httpd
IP Address: 192.168.1.1

+++++192.168.1.2+++++
Port Number: 80
......
product: Apache http
IP Address: 192.168.1.2

+++++192.168.1.3+++++
Port Number: 80
......
product: Apache httpd
IP Address: 192.168.1.3

+++++192.168.1.4+++++
Port Number: 3306
......
product: MySQL
IP Address: 192.168.1.4

+++++192.168.1.5+++++
Port Number: 22
......
product: Open SSH
IP Address: 192.168.1.5

+++++192.168.1.6+++++
Port Number: 80
......
product: Apache httpd
IP Address: 192.168.1.6

Ожидаемый результат:

These hosts have Apache services:

192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.6

Код, который я пробовал:

for service in f:
    if "product: Apache httpd" in service:
        for host in f:
            if "IP Address: " in host:
                print(host[5:], service)

Он просто дал мне все IP-адреса вместо конкретных хостов с установленным Apache.

Как я могу сделать ожидаемый результат?

4 ответа

Решение

Вы также можете попробовать это:

apaches = []
with open('ips.txt') as f:
    sections = f.read().split('\n\n')

    for section in sections:
        _, _, _, product, ip = section.split('\n')
        _, product_type = product.split(':')
        _, address = ip.split(':')

        if product_type.strip().startswith('Apache'):
            apaches.append(address.strip())

print('These hosts have Apache services:\n%s' % '\n'.join(apaches))

Какие выходы:

These hosts have Apache services:
192.168.1.1
192.168.1.2
192.168.1.3
192.168.1.6

Может быть, как-то так. Я привел данные для иллюстрации, но они также могут быть получены из файла.

Кроме того, сначала мы собираем все данные для каждого хоста, на случай, если вам понадобится и другая информация, а затем распечатываем то, что нужно. Это означает info_by_ip выглядит примерно как

{'192.168.1.1': {'Port Number': '80', 'product': 'Apache httpd'},
 '192.168.1.2': {'Port Number': '80', 'product': 'Apache http'},
 '192.168.1.3': {'Port Number': '80', 'product': 'Apache httpd'},
 '192.168.1.4': {'Port Number': '3306', 'product': 'MySQL'},
 '192.168.1.5': {'Port Number': '22', 'product': 'Open SSH'},
 '192.168.1.6': {'Port Number': '80', 'product': 'Apache httpd'}}

,

Код:

import collections

data = """
+++++192.168.1.1+++++
Port Number: 80
......
product: Apache httpd

+++++192.168.1.2+++++
Port Number: 80
......
product: Apache http

+++++192.168.1.3+++++
Port Number: 80
......
product: Apache httpd

+++++192.168.1.4+++++
Port Number: 3306
......
product: MySQL

+++++192.168.1.5+++++
Port Number: 22
......
product: Open SSH

+++++192.168.1.6+++++
Port Number: 80
......
product: Apache httpd
"""

ip = None  # Current IP address

# A defaultdict lets us conveniently add per-IP data without having to
# create the inner dicts explicitly:
info_by_ip = collections.defaultdict(dict)

for line in data.splitlines():  # replace with `for line in file:` for file purposes
    if line.startswith('+++++'):  # Seems like an IP address separator
        ip = line.strip('+')  # Remove + signs from both ends
        continue  # Skip to next line
    if ':' in line:  # If the line contains a colon,
        key, value = line.split(':', 1)  # ... split by it, 
        info_by_ip[ip][key.strip()] = value.strip()  # ... and add to this IP's dict.


for ip, info in info_by_ip.items():
    if info.get('product') == 'Apache httpd':
        print(ip)

Вы можете использовать +++++ в качестве вашего разделителя и получить желаемый IP с помощью следующего кода.

    with open('ip.txt', 'r') as fileReadObj:
    rows = fileReadObj.read()
    text_lines = rows.split('+++++')
    for i, row in enumerate(text_lines):
        if 'Apache' in str(row):
            print(text_lines[i - 1])

Для объяснения:

with open(filename,'r') as fobj: # Open the file as read only
    search_string = fobj.read() # Read file into string
    print('These hosts have Apache services:\n\n')
    # Split string by search term
    for string_piece in search_string.split('Apache'):  
        # Split string to isolate IP and count up/back 2
        ip_addr = string_piece.split('+++++')[-2] 
        print(ip_addr)

Сжатый:

with open(filename,'r') as fobj:
    print('These hosts have Apache services:\n\n')
    for string_piece in fobj.read().split('Apache'):
        print('{}\n'.format(string_piece.split('+++++')[-2]))
Другие вопросы по тегам