使用bash / awk / sed将IP范围转换为离散的ip号码

时间:2010-10-23 23:15:38

标签: sed awk

我正在处理作为acl请求创建的IP源/目标/端口列表 该请求看起来像这样:

source IP    destination IP  Port
76.211.12.9  10.112.12.232   1521

源IP和目标IP有三种不同的格式

  1. X.X.X.X,Y,Z
  2. X.X.X.X-Z
  3. X.X.X.X,y.y.y.y,Z,Z,Z,Z
  4. 我想创建输出

    1. X.X.X.X
      x.x.x.y
      x.x.x.z
    2. X.X.X.X
      x.x.x.y
      x.x.x.z
    3. X.X.X.X
      y.y.y.y
      z.z.z.z
    4. 使用bash,sed,awk我该怎么做到这一点? 在我的例子中:

      76.211.12.9,10,11 10.112.12.232 1521
      76.211.12.9-11 10.112.12.232 1521
      

      两个输出都是这样的:

      76.211.12.9 10.112.12.232 1521
      76.211.12.10 10.112.12.232 1521
      76.211.12.11 10.112.12.232 1521
      

3 个答案:

答案 0 :(得分:1)

BEGIN { DEBUG = 0 }

function setup(first_split, second_split) {
  src = $1; dst = $2; port = $3
  j = split(src, src_a, first_split)
  k = split(src_a[4], src_a_2, second_split)
  if(DEBUG)
    print "<" first_split second_split ">", j, k, "\n" src
}

/^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*,[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/ {
  setup(",", ",")
  for(i = 1; i <= j; ++i)
    print src_a[i], dst, port
  next
}

/^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*,[0-9][0-9]*[ ,]/ {
  setup(".", ",")
  for(i = 1; i <= k; ++i)
    print src_a[1] "." src_a[2]"." src_a[3] "." src_a_2[i], dst, port
  next
}

/^[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*-/ {
  setup(".", "-")
  for(i = src_a_2[1]; i <= src_a_2[2]; ++i)
    print src_a[1] "." src_a[2] "." src_a[3] "." i, dst, port
  next
}

{ print }

我的测试文件:

76.211.77.7 10.112.12.232 1521
76.211.77.8 10.112.12.232 1521
76.211.77.9,10,11 10.112.12.232 1521
76.211.77.12-13 10.112.12.232 1521
76.211.77.14,76.211.77.15,76.211.77.16 10.112.12.232 1521

此脚本可以在One True Awk中使用,也可以在gawk中使用。

答案 1 :(得分:1)

为了将awk解决方案从我对所有三个字段的其他答案中概括出来,我认为我们最终只能将awk用作通用编程语言。

现在,awk很精彩,而在1970年代中期,当Unix出现时,它就是一个集体软件Renaissance。但高级语言也加入了Unix软件工具俱乐部,实际上,我宁愿用Ruby编写它......

Ruby这次,看到我对Awk方法的另一个答案......

class IPMacro
  private_class_method :new
  def self.get_base a
    @@root = a[0].split('.').tap { |x| @@last = x[3] || x[0] }.take(3).join('.')
  end
  def self.expand_last_comma a
    self.get_base a
    [a[0], *(a.drop(1).map { |e| [@@root, e].join('.') })]
  end
  def self.expand_last_dash a
    self.get_base a
    @@root = @@root['.'] ? [@@root] : []
    [*(@@last..a[1]).to_a.map do |e|
        (@@root +  [String(e)]).join '.'
      end
    ]
  end
  def self.expand f
    a = f.split ','
    if a[1]
      return self.expand_last_comma a unless a[1]['.'] || !a[0]['.']
    else
      a = f.split '-'
      return self.expand_last_dash a if a[1]
    end
    return [*a]
  end
  def self.run
    $<.each_line do |line|
      a = line.split(' ').map do |f|
        self.expand f
      end
      a[0].each do |a1|
        a[1].each do |a2|
          a[2].each do |a3|
            puts '%s %s %s' % [a1, a2, a3]
          end
        end
      end
    end
  end
  self
end.run

这次我的测试案例是......

76.211.77.5 10.112.12.227 1400,1401,1402
76.211.77.6 10.112.12.228-231 1510-1515
76.211.77.7 10.112.12.232 1521
76.211.77.8 10.112.12.232 1521
76.211.77.9,10,11 10.112.12.232 1521
76.211.77.12-13 10.112.12.232 1521
76.211.77.14,76.211.77.15,76.211.77.16 10.112.12.232 1521

答案 2 :(得分:0)

Expletive删除了老兄! 这是一些甜蜜的代码。 十分优雅.. 这正是我所需要的。我针对我的340行数据运行它,并生成超过7500个单独的src / dest / port对。

由于