AWK子记录(记录内记录)

时间:2014-07-29 08:19:36

标签: awk

在awk中处理记录内记录的最佳方法是什么?

我有以

开头的记录
Network: 125
 <junk data>
  MAC: AA:AA:AA:AA:AA:AA
  Packets: 5125
 <junk data>
   Client: 1
     <junk data>
      MAC: 30:85:a9:b0:ec:c4
      Packets: 942
     <junk data>
   Client: 2
     <junk data>
      MAC: 30:85:a9:b0:ec:fa
      Packets: 1052
     <junk data>
 <junk data>
Network: 126
...

预期输出

---------------------------
Network: 125
Client: 30:85:a9:b0:ec:c4
Packets: 942
---------------------------

---------------------------
Network: 125
Client: 30:85:a9:b0:ec:fa
Packets: 1052
---------------------------

注意:输出结果包括来自网络机构本身的任何数据,如MAC:AA:AA:AA:AA:AA:AA。

首先我必须设置

{RS =&#34; Network&#34; ; FS =&#34; \ n&#34; }   然后做一些标准匹配,然后我必须检查客户端子记录,并做一些标准匹配,如果匹配,只打印出这个内部记录中的某些字段。

是否有RSS&#34; Sub记录&#34;功能在awk?

awk的~32000字段NF限制也存在问题。我必须处理的数据远不止于此。

谢谢!

3 个答案:

答案 0 :(得分:4)

我认为这样做符合你的要求:

awk 'BEGIN { FS=OFS=": "; hr="----------------" }
!h {print hr; h=1} 
/Network/ {n=$2} 
/Client/ {c=1} 
c && /MAC/ {m=$2} 
c && /Packets/ {p=$2} 
m && p {
    print "Network", n
    print "Client", m 
    print "Packets", p
    print hr "\n"
    m=c=p=h=""
}' input
  • h标志为false时,打印水平线。
  • 将网络保存到n
  • 仅在客户端
  • 内将客户端标志设置为true
  • 将客户端MAC保存到m
  • 将数据包保存到p
  • 设置mp时,打印输出和取消设置标记。

输出:

----------------
Network: 125
Client: 30:85:a9:b0:ec:c4
Packets: 942
----------------

----------------
Network: 125
Client: 30:85:a9:b0:ec:fa
Packets: 1052
----------------

这适用于您显示的输入,但如果Name: Value之间的空格数可能不同,您可能需要更改字段分隔符FS="[[:space:]]*:[[:space:]]+"(零个或多个空格字符,冒号) ,然后是一个或多个空格字符)。由于MAC地址也包含冒号,因此字段分隔符此时必须至少包含一个空格。如果这是一个问题,请告诉我。

答案 1 :(得分:1)

使用GNU Awk:

gawk -v RS='Network: ' -F 'Client: ' -v hl=--------------------------- '{gsub(/\n.*$/, "", $1); for(i=2;i<=NF;++i){if(match($i, /.*MAC: ([[:alnum:]:]+).*Packets: ([0-9]+).*/, a)) printf "%s\nNetwork: %s\nClient: %s\nPackets: %s\n%s\n\n", hl, $1, a[1], a[2], hl } }' file

脚本版本:

#!/usr/bin/gawk -f
BEGIN {
    RS = "Network: "
    FS = "Client: "
    hl = "---------------------------"
}
{
    gsub(/\n.*$/, "", $1)
    for (i = 2; i <= NF; ++i)
        if (match($i, /.*MAC: ([[:alnum:]:]+).*Packets: ([0-9]+).*/, a))
            printf "%s\nNetwork: %s\nClient: %s\nPackets: %s\n%s\n\n", hl, $1, a[1], a[2], hl
}

输出:

---------------------------
Network: 125
Client: 30:85:a9:b0:ec:c4
Packets: 942
---------------------------

---------------------------
Network: 125
Client: 30:85:a9:b0:ec:fa
Packets: 1052
---------------------------
...

答案 2 :(得分:0)

awk中的一种方式

awk '/^Network/{a=$0}/    MAC:/{b=$2}
/    Packets/{print"------------------------------\n" a"\n","Client: "b"\n",$0"\n------------------------------"}' file

在客户端上设置标志的另一种方法。

awk 'BEGIN{c="------------------------------\n"}
{gsub(/[ ][ ]+/,"")}
/^Network/{a=$0;x=0}
/Client/{x=1}
x&&/MAC:/{b=$2}
x&&/Packets/{print c a"\n","Client: "b"\n",$0"\n"c}' file