【问题标题】:Arp Scan results to delimited file with pipe delimiterArp 扫描结果到带有管道分隔符的分隔文件
【发布时间】:2019-03-13 05:02:32
【问题描述】:

为每一行创建一个包含 arp 扫描结果的文件,如下所示:

192.168.103.216   c4:2f:90:e5:8d:31    Hangzhou Hikvision

我想在 IP 地址和 MAC 地址之后添加一个管道分隔符,因此最终文件将如下所示:

192.168.103.216|c4:2f:90:e5:8d:31|Hangzhou Hikvision

不同的 ARP 扫描会产生不同的 IP 和 MAC,所以我必须匹配 IP 地址和 MAC 地址的模式,然后将 |在 IP 地址和 MAC 地址之后。或者我可以放一个 | MAC 地址的开头和 MAC 地址的结尾。结果是一样的。

我知道 sed 可以将 IP 地址与以下内容匹配:

sed '/\n/!s/[0-9.]\+/\n&\n/;/^\([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\n/P;D'

我想我可以仅使用[0-9A-Z:] 作为模式将 MAC 地址与类似语句匹配。

应该很容易浏览文件并添加分隔符。有没有更简单的方法来做到这一点?

【问题讨论】:

    标签: awk sed


    【解决方案1】:

    仅当您的文件完全一样时,并且为简洁起见,使用 GNU awk:

    awk '$3=$3" "$4{NF--}1' OFS=\| file
    192.168.103.216|c4:2f:90:e5:8d:31|Hangzhou Hikvision
    

    如果主机名可以有多个空格:

    awk '{for(i=4;i<=NF;i++)$3=$3" "$i;NF=3}1' OFS=\| file
    

    【讨论】:

    • 第二个 awk 语句就像一个魅力,因为主机名/制造商列可以有多个空格。非常感谢。
    【解决方案2】:

    使用awk;它使过程变得更加简单。

    awk 'BEGIN { OFS = "|" } { $1 = "" $1; print }'
    

    将输出字段分隔符从空格更改为管道符号。然后打印输入,但您必须更改某些内容以触发使用新 OFS 重新格式化,并在 $1 前添加一个空字符串来实现。

    【讨论】:

      【解决方案3】:

      编辑: 添加解决方案,该解决方案也将处理剩余空间。完全基于仅显示的样本。还有一件事,这个解决方案只会在 ips 和 mac 地址之后打印带有管道的行,如果两者都匹配,否则它只会打印该行。

      awk --re-interval '
      {
        $1=$1
      }
      match($0,/([0-9]+\.){3}[0-9]+ /){
        val=substr($0,RSTART,RLENGTH-1)"|"
        $0=substr($0,RSTART+RLENGTH)
      }
      match($0,/([[:xdigit:]]+:){5}[[:xdigit:]]+ /){
        print val substr($0,RSTART,RLENGTH-1)"|" substr($0,RSTART+RLENGTH)
        next
      }
      1
      '  Input_file
      


      您能否尝试以下操作(仅使用提供的示例进行测试,使用 GNU awk,我们也可以缩短它,但由于我有旧版本的 awk,我稍后会尝试添加它)。

      awk '{sub(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/,"&|");sub(/[[:xdigit:]]+:[[:xdigit:]]+:[[:xdigit:]]+:[[:xdigit:]]+:[[:xdigit:]]+:[[:xdigit:]]+/,"&|")} 1' Input_file
      

      或以上代码的正则表达式也可以缩短为如下。

      awk --re-interval '{sub(/([0-9]+\.){3}[0-9]+/,"&|");sub(/([[:xdigit:]]+:){5}[[:xdigit:]]+/,"&|")} 1' Input_file
      

      或者使用 gsub 并在单个 gsub 本身中提及正则表达式。

      awk --re-interval '{gsub(/([0-9]+\.){3}[0-9]+|([[:xdigit:]]+:){5}[[:xdigit:]]+/,"&|")} 1' Input_file
      

      如果您想将输出保存到 Input_file 本身,那么也将&gt; temp_file &amp;&amp; mv temp_file Input_file 附加到上面的代码中。



      sed 解决方案: 使用 GNU sed 测试。

      sed -E 's/([0-9]+\.){3}[0-9]+|([[:xdigit:]]+:){5}[[:xdigit:]]+/&|/g' Input_file
      

      注意:我正在使用--re-interval,因为它很旧,否则你可以删除它,如果你有最新版本的awk 与你(GNU awk )

      【讨论】:

      • 所有示例在我的 debian 机器上运行良好。他们不像接受的答案那样处理字段之间的空格,但我并没有在我原来的问题中真正提出这个要求。
      • @WilliamK,好的,假设您的 Input_file 与显示的示例相同,如果是这种情况,那么您能否尝试以下操作。再次 - 它认为您的 Input_file 与显示的示例完全相同:awk --re-interval -v OFS="" '{$1=$1;gsub(/([0-9]+\.){3}[0-9]+|([[:xdigit:]]+:){5}[[:xdigit:]]+/,"&amp;|")} 1' Input_file 那么让我知道吗? PS:这些代码的 + 点是它的字段编号不是硬编码的,所以任何 IP 或 Mac 都将与 | 连接。
      • @WilliamK,很高兴您选择了一个正确的答案,您也可以做些什么来鼓励其他好的答案,您可以看到一次stackoverflow.com/help/someone-answers
      • @WilliamK,请检查我的 EDIT 命令一次,如果对您有帮助,请告诉我。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      • 1970-01-01
      • 2014-04-03
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      • 1970-01-01
      相关资源
      最近更新 更多