【问题标题】:removing leading zeros from IP addresses: converting ipfilter.dat to bluetack.co.uk ipfilter with sed从 IP 地址中删除前导零:使用 sed 将 ipfilter.dat 转换为 bluetack.co.uk ipfilter
【发布时间】:2011-04-01 13:55:49
【问题描述】:

我需要将 uTorrent 风格的 ipfilter.dat 转换为 bluetack 风格的 ipfilter 文件,并编写了这个 shell 脚本来实现这一点:

#!/bin/bash

# read ipfilter.dat-formatted file line by line
# (example: 000.000.000.000-008.008.003.255,000,Badnet
# - ***here, input file's lines/fields are always the same length***)
# and convert into a bluetack.co.uk-formatted output
# (example: Badnet:0.0.0.0-8.8.3.255
# - fields moved around, leading zeros removed)

while read record
do
start=`echo ${record:0:15} | awk -F '.' '{for(i=1;i<=NF;i++)$i=$i+0;}1' OFS='.'`
end=`echo ${record:16:15} | awk -F '.' '{for(i=1;i<=NF;i++)$i=$i+0;}1' OFS='.'`
echo ${record:36:7}:${start}-${end}
done < $1

但是,在 2000 行的输入文件上,此脚本平均需要 10(!) 秒才能完成 - 仅需 200 行/秒。

我确信使用 sed 也可以达到同样的效果,而且 sed-version 可能要快得多。

是否有 sed-guru 为这种固定位置替换提出解决方案?

您也可以随意提出其他语言的解决方案 - 例如,我会喜欢测试 Python 或 C 版本。我们也欢迎更高效的 shell/bash 版本。

【问题讨论】:

    标签: performance bash sed awk


    【解决方案1】:

    你可以试试这个。

    sed -r 's/^0*([0-9]+)\.0*([0-9]+)\.0*([0-9]+)\.0*([0-9]+)-0*([0-9]+)\.0*([0-9]+)\.0*([0-9]+)\.0*([0-9]+),...,(.*)$/\9:\1.\2.\3.\4-\5.\6.\7.\8/' inputfile
    

    我没有测试性能,但我猜它可能会超过 200 行/秒。

    【讨论】:

    • 嗯,在理解了您的 sed 行之后 - 它确实比我想象的要容易,可以通过可管理的努力实现相同的目标。谢谢 - 下次我会知道如何用 sed 解决类似的问题。
    【解决方案2】:

    在大文件上使用 shell 的 while 读取循环会牺牲性能。经验证明,awk/sed(和某些语言,例如 Perl/Python/Ruby)等工具在迭代大文件和处理行方面比 shell 的 while read 循环更好。此外,在您的脚本中,在遍历行的同时,您还通过管道对awk 进行了几次调用。这是额外的开销。

    Ruby(1.9+)

    $ cat file
    000.000.000.000-008.008.003.255,000,Badnet
    001.010.110.111-002.020.220.222,111,Badnet
    
    $ ruby -F"," -ane 'puts "#{$F[-1].chomp}:" + $F[0].gsub(/(00|0)([0-9]+)([.-])/,"\\2\\3")'   file
    Badnet:0.0.0.0-8.8.3.255
    Badnet:1.10.110.111-2.20.220.222
    

    【讨论】:

    • (只有在愚人节,独角兽才会对我的投票竖起大拇指吗?)我同意你对 shell(和我的脚本)的看法,尽管大多数时候它是用于这种简单数据操作的外壳。关于您的 Ruby 示例:它平均比 sed 快 - ~0.040s。谢谢这个!
    【解决方案3】:

    我真的很想让它在一个 sed 命令中工作,但我无法弄清楚。当然,这仍然会比 200 行/秒快。

    sed 's/\.0\{1,2\}/\./g' | sed 's/^0\{1,2\}//'

    【讨论】:

      【解决方案4】:

      #!/bin/tclsh

      #Regsub TCL script to remove the leading zeros from the ip address.
      
      #Author : Shoeb Masood , Bangalore
      
      puts "Enter the ip address"
      set ip [gets stdin]
      set list_ip [split $ip .]
      foreach index $list_ip {
      regsub  {^0|^00} $index {\1} index
      lappend list_ip2 $index
      }
      set list_ip2 [join $list_ip2 "."]
      puts $list_ip2
      

      【讨论】:

        猜你喜欢
        • 2012-04-14
        • 2020-01-20
        • 1970-01-01
        • 2014-09-16
        • 2015-03-18
        • 2017-06-13
        • 1970-01-01
        • 1970-01-01
        • 2021-11-27
        相关资源
        最近更新 更多