【问题标题】:Validate IP range with bash [closed]使用 bash 验证 IP 范围 [关闭]
【发布时间】:2016-02-16 05:25:09
【问题描述】:

我需要验证文件中的 IP 范围并更正它们。

文件有以下错误范围:

192.168.1.2-192.168.1.1
10.0.0.10-10.0.0.8
172.16.0.9-172.16.0.5

问题是结束地址不能在开始地址之前,应该更正为:

192.168.1.1-192.168.1.2
10.0.0.8-10.0.0.10
172.16.0.5-172.16.0.9

我的文件有很多这样的错误范围,所以自动更正方法会很棒。

【问题讨论】:

  • 为什么要“反转”最后一条记录?
  • 因为当我尝试使用 masscan 时,它会报告错误并且在纠正之前无法工作。 $ masscan -iL range.txt -oL res.txt -p 80 err: 结束 addr 10.0.0.8 不能在开始 addr 255.255.255.255 之前出现错误范围规范:“10.0.0.10-10.0.0.8”
  • 我认为问题是为什么在第三个例子中172.16.0.9 被认为是在之前 172.16.0.5
  • 对不起,你是对的,只是错误,已更正。

标签: bash sed grep


【解决方案1】:

喂,

您必须执行以下步骤:

  1. 阅读每一行
  2. 在ips中分割当前行
  3. 对两个ip排序
  4. 回显排序后的 ips

以下脚本执行此操作:

#!/bin/bash

filename="$1"
#Step1: read each line from file
#see http://stackoverflow.com/questions/10929453/bash-scripting-read-file-line-by-line
while read -r line
do
    #Step2: split each line in ips
    #see http://stackoverflow.com/questions/10586153/split-string-into-an-array-in-bash
    IFS='-' read -r -a array <<< "$line"

    #Step3: sort the ips
    #see http://stackoverflow.com/questions/7442417/how-to-sort-an-array-in-bash
    #for sorting ips see: https://www.madboa.com/geek/sort-addr/
    IFS=$'\n' sorted=($(sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 <<<"${array[*]}"))
    unset IFS
    #Step4: echo the results
    echo ${sorted[0]}"-"${sorted[1]}
done < "$filename"

以下文件的结果:

192.168.1.2-192.168.1.1
10.0.0.10-10.0.0.8
172.16.0.5-172.16.0.9

是:

192.168.1.1-192.168.1.2
10.0.0.8-10.0.0.10
172.16.0.5-172.16.0.9

【讨论】:

  • @Demontager:如果它“适用于我的样本”,那么您应该通过 meta.stackexchange.com/questions/5234/… 接受提供的答案。如果您没有正确指定您的问题,那么您应该通过编辑您的 Q 来要求澄清,而不是提供指向场外数据集的链接。祝你好运。
  • @Demontager:好节目!作为欢迎和仅供参考,我意识到好问题 A. 显示涵盖所有情况的 small 示例数据,包括应该跳过的“记录”和应该标记为“输入错误”的那些, B. 来自该样本数据的所需输出 ,C.包括解决问题的最佳尝试代码。 D. 您的代码和错误消息的当前输出(“它不工作”不是证据)。 E. 您对解决方案的最佳想法以及为什么它可能还没有奏效。祝你好运,继续发帖;-)
  • 警告:与其他一些情况不同(即,以常规命令为前缀的赋值语法),将IFS 设置在与使用新值相同的行(sorted=( ... )确实不 将 IFS 更改范围限定为这一行。将 IFS 分配转移到其他地方可能会提高清晰度 - 即。在循环之外——避免给读者一个错误的印象,即该分配实际上是如此范围的。
  • 顺便说一句,echo ${sorted[0]}"-"${sorted[1]}完全相反的良好做法,引用不需要引用的内容(字符串常量,没有空格或特殊外壳字符)并保留未引用的内容 确实 需要被引用以防止字符串拆分和全局扩展(即参数扩展)。请考虑使用echo "${sorted[0]}-${sorted[1]}"
  • 您也可以考虑完全避免使用数组:{ read -r first; read -r second; } &lt; &lt;(sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 &lt;&lt;&lt;"${array[*]}") 会将第一项和第二项读取到两个单独的变量中,firstsecond,没有原始的全局扩展副作用代码(看看如果你的文件中有一个*而不是IP地址会发生什么:由于$(sort ...)的未加引号的扩展,你将有一个当前目录中的文件列表替换到你的数组中)。
【解决方案2】:

鉴于您的示例输入/输出,那么您所需要的就是这个,将 GNU awk 用于 gensub():

$ awk -F- {print (gensub(/.*\./,"",1,$1) < gensub(/.*\./,"",1,$2) ? $1 FS $2 : $2 FS $1)}' file 
192.168.1.1-192.168.1.2
10.0.0.10-10.0.0.8
172.16.0.5-172.16.0.9

对于其他 awk,只需使用几个本地变量和 sub()。

但是,如果您需要一种解决方案,当 IP 地址的某些其他部分(而不只是最终段)在给定行上可能不同时(例如 172.16.0.5-172.15.0.9),那么这将适用于任何 awk:

$ cat tst.awk
BEGIN { FS="-" }
{
    split($1,t,/\./)
    beg = sprintf("%03d%03d%03d%03d", t[1], t[2], t[3], t[4])

    split($2,t,/\./)
    end = sprintf("%03d%03d%03d%03d", t[1], t[2], t[3], t[4])

    print (beg < end ? $1 FS $2 : $2 FS $1)
}

$ awk -f tst.awk file
192.168.1.1-192.168.1.2
10.0.0.8-10.0.0.10
172.16.0.5-172.16.0.9

$ echo '172.16.0.5-172.15.0.9' | awk -f tst.awk     
172.15.0.9-172.16.0.5

如果您正在考虑使用 shell 循环来处理文本,请确保您首先阅读并完全理解 https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice

【讨论】:

    猜你喜欢
    • 2015-06-04
    • 2014-07-03
    • 2011-03-06
    • 2011-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    相关资源
    最近更新 更多