【问题标题】:Parsing of ip address from netstat output on MacOS with awk使用 awk 从 MacOS 上的 netstat 输出解析 ip 地址
【发布时间】:2014-09-30 21:24:26
【问题描述】:

这是一个与 awk 相关的问题(请不要 perl/cut/sed... :))。

我实际上要做的是仅使用 awk 从 MacOS 上的 netstat 输出中获取目标地址。

这里是输出示例:

$ netstat -nl -p tcp
Active Internet connections
Proto Recv-Q Send-Q  Local Address          Foreign Address        (state)
tcp4       0      0  127.0.0.1.26164        127.0.0.1.50100        ESTABLISHED
tcp4       0      0  127.0.0.1.50100        127.0.0.1.26164        ESTABLISHED

如果我运行 awk 解析器,我会得到:

$ netstat -nl -p tcp | awk '/tcp/ {split($5,a,".") ; for(i=1; i<NF-1; i++) printf a[i] "."; printf "\n"}'
127.0.0.1.
127.0.0.1.

1)有没有办法删除“。”在 IP 地址的末尾?

2) 有没有更好的“awk”方式来获得相同的结果?

PS:我知道你可以输入类似的东西

$ netstat -nl -p tcp | perl -ape '$_=$F[4];s/((?:\d+\.){3}\d+)\D.*/$1\n/'

得到正确的结果;)

谢谢!

【问题讨论】:

    标签: macos awk


    【解决方案1】:

    只需使用来自split() 的元素数量:

    awk '/tcp/ {n=split($5,a,".")
                ^-----------------------------------------------------------\
                for(i=1; i<n; i++) printf "%s%s", a[i], (i==n-1?"\n":".")   |
                           ^-----------------------------^^^^^^-------------/
               }'
    

    说明

    • n=split($5,a,".") 与您一样拆分,但将生成的字段数量存储在变量 n 中。
    • for(i=1; i&lt;n; i++) printf "%s%s", a[i], (i==n-1?"\n":".")} 循环遍历这些值,根据循环时间打印一个点 . 或一个新行。

    测试

    $ netstat ... | awk '/tcp/ {n=split($5,a,"."); for(i=1; i<n; i++) printf "%s%s", a[i], (i==n-1?"\n":".")}'
    127.0.0.1
    127.0.0.1
    

    【讨论】:

      【解决方案2】:

      其他回复可能更好,但这是我的尝试:

      netstat -nl -p tcp | awk '/tcp/{split($5,a,".");for(x in a)if(a[x+1]""){y=y SEP a[x]; SEP="."}print y;y="";SEP=""}'
      

      说明

      • if(a[x+1]"") 检查数组中是否有下一个元素(即,如果它没有处理最后一个元素 - 端口),"" 通过应用连接将数字转换为字符串,因此 0 不会评估为 @ 987654327@
      • SEP 变量只是确保输出不会以 . 开头,并在最后重置。

      【讨论】:

      • 这个for (i in a) 可能会导致问题。见Why does awk seem to randomize the array?。由于顺序很重要,我建议您坚持使用for(i=0; i...) 语法。
      • 在我的机器上工作。开玩笑,但我尝试了更大的输入集,但它仍然没有随机化。使用GNU Awk 4.1.paste.ee/p/07ztE
      • 是的,我明白了,但你永远无法知道。另外,我建议添加一些大括号以更清楚地说明for 的范围是什么--> awk '/tcp/{split($5,a,"."); for(x in a) {if(a[x+1]""){y=y SEP a[x]} SEP="."} print y; y="";SEP=""}' file。我不是这个解决方案的忠实拥护者,因为重复分配SEP,最好利用split() 的输出。但是,+1 的解释。
      【解决方案3】:

      我认为我更喜欢这种方法,它有多种选择 FS - 点或空格:

      netstat -nl -p tcp |awk -F'[. ]*' '/tcp/{print $9,$10,$11,$12}' OFS="."
      

      【讨论】:

      • @fedorqui 哎呀,谢谢!我误读了这个问题 - 实际上理解他想要第 4-7 列:-)
      • 谢谢,两种方式我都喜欢。我无法使用 OFS...我错过了分隔字段选项中的星号。
      【解决方案4】:

      我认为这是使用 awk 最简单、最通用的方法

       awk '{match($5,/(.*)\./,x);print x[1]}' file
      

      【讨论】:

      • 实际上不适用于 awk 但 gawk。无论如何,这正是我正在考虑的,最短且优雅的解决方案:) )。谢谢!
      【解决方案5】:

      为什么不采用 UNIX 方式呢?将其通过管道传输到另一个实用程序:

      netstat -nl -p tcp | awk '/tcp/{print $4}' | sed 's/\.[0-9]*$//'
      

      或者,要在awk 中做整个事情,使用sub() 删除IP 的最后一部分:

      netstat -nl -p tcp | awk '/tcp/{sub(/\.[0-9]*$/,"",$4); print $4}' 
      

      不幸的是,BSD grep(这是 OSX 所拥有的)没有 -P 选项,否则你可以这样做:

      netstat -nl -p tcp | awk '/tcp/{print $4}' | grep -oP '.*(?=\.\d+)'
      

      【讨论】:

        猜你喜欢
        • 2021-02-20
        • 2015-03-06
        • 2015-09-14
        • 1970-01-01
        • 2014-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-15
        相关资源
        最近更新 更多