【问题标题】:python parse file for ip addressesip地址的python解析文件
【发布时间】:2012-12-24 23:40:59
【问题描述】:

我有一个包含多个 IP 地址的文件。 4行txt大约有900个IP。我希望输出为每行 1 个 IP。我怎样才能做到这一点?基于其他代码,我想出了这个,但它失败了,因为多个 IP 在单行上:

import sys
import re

try:
    if sys.argv[1:]:
        print "File: %s" % (sys.argv[1])
        logfile = sys.argv[1]
    else:
        logfile = raw_input("Please enter a log file to parse, e.g /var/log/secure: ")
    try:
        file = open(logfile, "r")
        ips = []
        for text in file.readlines():
           text = text.rstrip()
           regex = re.findall(r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})$',text)
           if regex is not None and regex not in ips:
               ips.append(regex)

        for ip in ips:
           outfile = open("/tmp/list.txt", "a")
           addy = "".join(ip)
           if addy is not '':
              print "IP: %s" % (addy)
              outfile.write(addy)
              outfile.write("\n")
    finally:
        file.close()
        outfile.close()
except IOError, (errno, strerror):
        print "I/O Error(%s) : %s" % (errno, strerror)

【问题讨论】:

  • 您正在寻找 IPv4 地址的规范形式。请注意,还有其他可接受的形式,即使是 IPv4 地址。例如如果您在 localhost 端口 80 (2130706433 == 0x7f000001 == 127.0.0.1) 上运行 HTTP 服务器,请尝试 2130706433。当然,如果你控制了文件的格式,你就不需要担心这些事情......但是,如果你可以切实地支持 IPv6,它将使你的脚本适应未来。
  • re.findall() 总是返回一个列表。它永远不是None

标签: python


【解决方案1】:

您的表达式中的$ 锚会阻止您找到除最后一个条目之外的任何内容。删除它,然后使用.findall()返回的列表:

found = re.findall(r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})',text)
ips.extend(found)

re.findall() 将始终返回一个列表,该列表可能为空。

  • 如果您只想要唯一的地址,请使用集合而不是列表。
  • 如果您需要验证 IP 地址(包括忽略私有网络和本地地址),请考虑使用ipaddress.IPV4Address() class

【讨论】:

    【解决方案2】:

    findall 函数返回一个匹配数组,您无需遍历每个匹配项。

    regex = re.findall(r'(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})$',text)
    if regex is not None:
        for match in regex:
            if match not in ips:
                ips.append(match)
    

    【讨论】:

      【解决方案3】:

      从文件中提取 IP 地址

      我在this discussion 中回答了类似的问题。简而言之,这是一个基于我正在进行的项目之一的解决方案,用于从不同类型的输入数据(例如字符串、文件、博客发布等)中提取基于网络和主机的指标:https://github.com/JohnnyWachter/intel


      我会导入 IPAddressesData 类,然后使用它们以下列方式完成您的任务:

      #!/usr/bin/env/python
      
      """Extract IPv4 Addresses From Input File."""
      
      from Data import CleanData  # Format and Clean the Input Data.
      from IPAddresses import ExtractIPs  # Extract IPs From Input Data.
      
      
      def get_ip_addresses(input_file_path):
          """"
          Read contents of input file and extract IPv4 Addresses.
          :param iput_file_path: fully qualified path to input file. Expecting str
          :returns: dictionary of IPv4 and IPv4-like Address lists
          :rtype: dict
          """
      
          input_data = []  # Empty list to house formatted input data.
      
          input_data.extend(CleanData(input_file_path).to_list())
      
          results = ExtractIPs(input_data).get_ipv4_results()
      
          return results
      
      • 现在您有了一个列表字典,您可以轻松访问所需的数据并以任何您想要的方式输出。下面的例子利用了上面的函数;将结果打印到控制台,并将它们写入指定的输出文件:

        # Extract the desired data using the aforementioned function.
        ipv4_list = get_ip_addresses('/path/to/input/file')
        
        # Open your output file in 'append' mode.
        with open('/path/to/output/file', 'a') as outfile:
        
            # Ensure that the list of valid IPv4 Addresses is not empty.
            if ipv4_list['valid_ips']:
        
                for ip_address in ipv4_list['valid_ips']:
        
                    # Print to console
                    print(ip_address)
        
                    # Write to output file.
                    outfile.write(ip_address)
        

      【讨论】:

        【解决方案4】:

        没有re.MULTILINE 标志$ 仅匹配字符串末尾。

        为了使调试更容易,将代码分成几个部分,您可以独立测试。

        def extract_ips(data):
            return re.findall(r"\d{1,3}(?:\.\d{1,3}){3}", data)
        

        如果输入文件很小,你不需要保留ips的原始顺序:

        with open(filename) as infile, open(outfilename, "w") as outfile:
            outfile.write("\n".join(set(extract_ips(infile.read()))))
        

        否则:

        with open(filename) as infile, open(outfilename, "w") as outfile:
            seen = set()
            for line in infile:
                for ip in extract_ips(line):
                    if ip not in seen:
                       seen.add(ip)
                       print >>outfile, ip
        

        【讨论】:

          猜你喜欢
          • 2015-06-02
          • 2017-05-14
          • 1970-01-01
          • 2014-12-09
          • 1970-01-01
          • 2015-09-14
          • 2010-09-27
          • 2020-08-06
          • 2014-10-11
          相关资源
          最近更新 更多