【问题标题】:Processing a log to fix a malformed IP address ?.?.?.x处理日志以修复格式错误的 IP 地址 ?.?.?.x
【发布时间】:2011-01-25 01:03:48
【问题描述】:

我想使用 shell 脚本将日志文件每一行的第一个字符“x”替换为数字“7”。日志文件示例:

216.129.119.x [01/Mar/2010:00:25:20 +0100] "GET /etc/....
74.131.77.x [01/Mar/2010:00:25:37 +0100] "GET /etc/....
222.168.17.x [01/Mar/2010:00:27:10 +0100] "GET /etc/....

我卑微的开始......

#!/bin/bash
echo Starting script...
cd /Users/me/logs/
gzip -d /Users/me/logs/access.log.gz
echo Files unzipped...
echo I'm totally lost here to process the log file and save it back to hd...

exit 0

为什么日志文件IP格式会这样?我的网络提供商 (1and1) 已决定不存储 IP 地址,因此他们将最后一个数字替换为字符“x”。他们告诉我这是“法律”的新要求。我个人认为这是 bs,但这会让我们偏离主题。

我想用 AWstats 处理这些日志文件,所以我需要一个没有格式错误的 IP 地址。我想将 x 替换为 7,如下所示:

216.129.119.7 [01/Mar/2010:00:25:20 +0100] "GET /etc/....
74.131.77.7 [01/Mar/2010:00:25:37 +0100] "GET /etc/....
222.168.17.7 [01/Mar/2010:00:27:10 +0100] "GET /etc/....

我知道并不完美,但至少我可以处理文件,我仍然可以获得很多有用的信息,如国家、访问者数量等。日志文件每个 200MB,所以我认为 shell 脚本是走的路,因为我可以在本地的 Macbook Pro 上快速做到这一点。不幸的是,我对 shell 脚本知之甚少,而且我的 javascript 技能这次也不会削减它。感谢您的帮助。

【问题讨论】:

    标签: python perl bash string shell


    【解决方案1】:

    您可以使用这个小 Python 脚本(可能写的行数可能比这个少):

    import sys
    for line in sys.stdin:
        ip_number, rest = line.split(' ', 1)
        ip_parts = ip_number.split('.')
        ip_parts[3] = '7'
        ip_number = '.'.join(ip_parts)
        print ip_number, rest,
    

    另存为fixip.py并执行为:

    cat access.log | python fixip.py > output.txt
    

    【讨论】:

    • 即使我使用了正确的命令“cat access.log | python fixip.py”,这个输出到我的终端,而不是我需要的文件。
    • 在 Unix 中,“一切都是文件”,因此您可以使用 ">" 指令将输出直接重定向到文件中。我会更新上面的命令。
    【解决方案2】:

    下面的 perl 单行代码应该可以解决问题:

    perl -p -i -e 's/\.x/\.7/' foo.log

    它将在日志文件的每一行上用“.7”替换“.x”的第一个实例。

    【讨论】:

    • 应该有并且做到了。但我需要双重转义它才能正确出现在帖子中。谢谢指点
    • 这很奏效。我确实尝试了所有解决方案,但这很快并且直接适合我的脚本。它在 25 秒内完成了 240MB 的日志记录。
    【解决方案3】:

    由于每个人都在发布他们的替代解决方案,我将发布一个我认为非常简单的解决方案:

    sed s/\.x/\.7/ input_file > output_file
    

    用“.7”替换任何字符串“.x”

    希望对您有所帮助! :)

    【讨论】:

      【解决方案4】:

      Python(使用要处理的文件作为第一个参数运行):

      import sys
      import gzip
      
      fin = gzip.GzipFile(sys.argv[1], 'r')
      fout = gzip.GzipFile(sys.argv[1] + '.new', 'w', 9)
      
      for line in fin:
        address, rest = line.split(' ', 1)
        prefix, node = address.rsplit('.', 1)
        fout.write('%s.7 %s' % (prefix, rest))
      
      fin.close()
      fout.close()
      

      【讨论】:

        【解决方案5】:

        虽然我不知道在每个 IP 中添加“7”的目的是什么,因为这不准确,但这里有一个 awk 单行代码

        $ awk '{sub(/x$/,7,$1)}1' file
        216.129.119.7 [01/Mar/2010:00:25:20 +0100] "GET /etc/....
        74.131.77.7 [01/Mar/2010:00:25:37 +0100] "GET /etc/....
        222.168.17.7 [01/Mar/2010:00:27:10 +0100] "GET /etc/....
        

        【讨论】:

        • 在每个 IP 的末尾放一个 7 的目的是因为我的 ISP 已经删除了 IP 的最后一部分并在适当的位置放置了一个 x。我认为大多数 ISP 都会为他们的客户提供 256 块。同一国家/地区的访问者来自同一 ISP 块范围的机会很小。 216.129.119.7 确实与 216.129.119.38 来自同一个国家,在本例中为美国。我喜欢数字 7,它和我可以使用的任何其他数字一样好? ;)
        • @skymook 我会选择255 ;-)
        猜你喜欢
        • 1970-01-01
        • 2021-07-28
        • 1970-01-01
        • 2015-05-30
        • 1970-01-01
        • 2014-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多