Python Parse file with Regex
Question: I am hoping someone might be able to get me on the right track here. I need to
parse nmap output with Python. I think using regex is going to be the right
method for this, but I have never worked with regex. Here is a sample of the
text I need to parse --> <http://pastebin.com/QhG86D7D>

What I need to do with this file is:

  1. I need the IP addresses.
  2. I need the open ports.

The trick is I need to obviously keep the IP and ports tied together as I will
be importing them into a database that will show what ports are open for each
IP.

I am also thinking I should write the logic into a function so I can parse
different files with larger numbers of hosts.

I do know how to read the file into my script and put the data into my
database. Where I am stuck is with the regex to parse out the data I need. Can
someone help me out?

Thanks in advance!


Answer: The following approach should get you started:

    
    
    import re
    
    nmap = """Host: 127.0.0.1 ()      Status: Up
    Host: 127.0.0.1 ()      Ports: 22/open/tcp//ssh///, 80/open/tcp//http///, 443/open/tcp//https///        Ignored State: closed (65532)
    Host: 127.0.0.2 ()      Status: Up
    Host: 127.0.0.2 ()      Ports: 21/open/tcp//ftp///, 22/open/tcp//ssh///, 25/open/tcp//smtp///, 53/filtered/tcp//domain///, 80/open/tcp//http///, 110/open/tcp//pop3///, 143/open/tcp//imap///, 443/open/tcp//https///, 465/filtered/tcp//smtps///, 993/open/tcp//imaps///, 995/open/tcp//pop3s///, 5222/filtered/tcp//xmpp-client///    Ignored State: closed (65523)
    # Nmap done at Sat Nov  7 10:40:36 2015 -- 2 IP addresses (2 hosts up) scanned in 32.07 seconds"""
    
    entries = []
    
    for line in nmap.split('\n'):
        re_host = re.match(r'Host\: ([0-9.]+?)\s+', line)
        if re_host:
            host = re_host.group(1)
            ports = re.findall('(\d+)\/open', line)
    
            if len(ports):
                entries.append((host,  ports))
    
    for host, ports in entries:
        print '{:16} {}'.format(host, ports)
    

This would display the following output:

    
    
    127.0.0.1        ['22', '80', '443']
    127.0.0.2        ['21', '22', '25', '80', '110', '143', '443', '993', '995']
    

You would want to replace the `split` with reading from your file.

