【问题标题】:Extracting contents from a header and parts of payload从标头和部分有效负载中提取内容
【发布时间】:2017-04-24 18:56:22
【问题描述】:

我在 data.log 文件中有以下内容。我希望提取 ts 值和有效载荷的一部分(在有效载荷中的 deadbeef 之后,第三行,从倒数第二个字节开始。请参考预期输出)。

data.log

print 1: file offset 0x0
ts=0x584819041ff529e0 2016-12-07 14:13:24.124834649 UTC
type: ERF Ethernet
dserror=0 rxerror=0 trunc=0 vlen=0 iface=1 rlen=96 lctr=0 wlen=68
pad=0x00 offset=0x00
dst=aa:bb:cc:dd:ee:ff src=ca:fe:ba:be:ca:fe
etype=0x0800
45 00 00 32 00 00 40 00 40 11 50 ff c0 a8 34 35         E..2..@.@.P...45
c0 a8 34 36 80 01 00 00 00 1e 00 00 08 08 08 08         ..46............
08 08 50 e6 61 c3 85 21 01 00 de ad be ef 85 d7         ..P.a..!........
91 21 6f 9a 32 94 fd 07 01 00 de ad be ef 85 d7         .!o.2...........


print 2: file offset 0x60
ts=0x584819041ff52b00 2016-12-07 14:13:24.124834716 UTC
type: ERF Ethernet
dserror=0 rxerror=0 trunc=0 vlen=0 iface=1 rlen=96 lctr=0 wlen=68
pad=0x00 offset=0x00
dst=aa:bb:cc:dd:ee:ff src=ca:fe:ba:be:ca:fe
etype=0x0800
45 00 00 32 00 00 40 00 40 11 50 ff c0 a8 34 35         E..2..@.@.P...45
c0 a8 34 36 80 01 00 00 00 1e 00 00 08 08 08 08         ..46............
08 08 68 e7 61 c3 85 21 01 00 de ad be ef 86 d7         ..h.a..!........
91 21 c5 34 77 bd fd 07 01 00 de ad be ef 86 d7         .!.4w...........

print 3806: file offset 0x592e0
ts=0x584819042006b840 2016-12-07 14:13:24.125102535 UTC
type: ERF Ethernet
dserror=0 rxerror=0 trunc=0 vlen=0 iface=1 rlen=96 lctr=0 wlen=68
pad=0x00 offset=0x00
dst=aa:bb:cc:dd:ee:ff src=ca:fe:ba:be:ca:fe
etype=0x0800
45 00 00 32 00 00 40 00 40 11 50 ff c0 a8 34 35         E..2..@.@.P...45
c0 a8 34 36 80 01 00 00 00 1e 00 00 08 08 08 08         ..46............
08 08 50 74 73 c3 85 21 01 00 de ad be ef 62 e6         ..Pts..!......b.
91 21 ed 4a 8c df fd 07 01 00 de ad be ef 62 e6         .!.J..........b.

我的预期输出

0x584819041ff529e0,85d79121
0x584819041ff52b00,86d79121
0x584819042006b840,62e69121

到目前为止我已经尝试过什么

我能够提取 ts 值。我用过

 awk -v ORS="" '$NF == "UTC"{print sep$1; sep=","} END{print "\n"}' data.log
 >> ts=0x584819041ff529e0,ts=0x584819041ff52b00

但是没有成功提取payload内容。

非常感谢任何帮助。

【问题讨论】:

  • 您的日志文件示例中没有字符串 86d79121。它是您预期输出的一部分吗?
  • 您的日志文件中有两个de ad be ef 实例?您希望如何区分它?
  • 嗨 Inian,它在日志文件中。请检查有效载荷中的(第一个) deadbeef 之后是否可以找到它。
  • 同意,请参考我的下一条评论?当出现两次相同的字符串时,您希望如何区分所需的字符串。
  • 有 3 个输入块,但只有 2 行预期输出。为什么? deadbeef 总是完全在一行上还是可以跨行拆分?

标签: python regex awk sed scripting


【解决方案1】:

这是完成它的一种方法:

awk -F '=| ' '/^ts=/{printf $2","} /de ad be ef/{if(!a){printf $15$16;a=1}else{print $1$2;a=0}}' data.log

输出:

0x584819041ff529e0,85d79121
0x584819041ff52b00,86d79121

解释:

-F '=| '                 : set the field seperator to both '=' and 'space'
/^ts=/{printf $2","}     : if pattern 'ts=' found at line beginning, print the second field
/de ad be ef/{something} : if pattern 'de ad be ef' found, do 'something'

初始变量a 将等于0。如果第一次找到模式de ad be efif(!a) 将成功并因此打印15th16th 字段。现在将a 设置为1。因此,当de ad be ef 模式在下一行匹配时,if(!a) 检查将失败并因此打印1st2nd 字段。现在,将a 重置为0 并为文件的其余部分继续相同的过程。

【讨论】:

  • 您能否详细介绍一下代码的作用?谢谢
  • 感谢您提供详细信息。原因是您的命令对于测试用例 3 失败(添加到问题中)。谢谢
  • 现在检查.. 这是因为 /ts/ 在第 3 组的情况下匹配 'Pts'
  • 永远不要使用printf $2,永远不要使用printf "%s",$2。前者告诉 awk 使用输入数据作为格式说明符,因此当输入包含像 %s 这样的格式字符时会神秘地失败。
【解决方案2】:

如果你想要 sed:

sed -n -e '/^ts/ {s/^ts=\([^ ]*\) \(.*\)/\1/; H;};' \
       -e '/de ad be ef/ {N; s/\(.*\)de ad be ef \([0-9a-f]\+\) \([0-9a-f]\+\) \(.*\) \([0-9a-f]\+\) \([0-9a-f]\+\) \(.*\)/,\2\3\5\6/; H;};' \
       -e '$ {x; s/\n,/,/g p;}' file

如果您对更多信息感兴趣,请询问。

【讨论】:

  • 谢谢。对于较大的条目,您的解决方案似乎比接受的答案需要更长的时间。
  • sed 用于在单个行上进行简单替换,仅此而已。对于任何其他您使用的结构,这些结构在 1970 年代中期 awk 被发明时已经过时,正如这里所见,awk 解决方案将更清晰、更快、更便携、更易于扩展,并且在几乎所有其他理想属性方面都更好软件。
【解决方案3】:

使用 deadbeef 作为开关的 awk 变体

awk -F '[= ]' '/^ts/{s=$2",";a=15} /de ad be ef/{s=s $a $(a+1);if(a==1)print s;a=1}' data.log

还有一个 sed 变体

sed -n -e '/^ts=/{h;b^J}' -e "/de ad be ef/,//{H;g;s/ts=\([^ ]*\).*\n*de ad be ef \(..\) \(..\).*\n\(..\) \(..\).*/\1,\2\3\4\4/p;}" data.log

info: "^J" 在 posix 版本中是 CTRL+J (新行字符),在 GNU 版本中是 ";"

【讨论】:

    【解决方案4】:

    使用 GNU awk 进行 gensub():

    $ awk -v RS= '{
        gsub(/(  |\t)+[^\n]*(\n|$)/," ")
        print gensub(/.*\nts=(\S+).*de ad be ef (..) (..) (..) (..).*/,"\\1,\\2\\3\\4\\5\\6",1)
    }' data.log
    0x584819041ff529e0,85d79121
    0x584819041ff52b00,86d79121
    0x584819042006b840,62e69121
    

    即使 deadbeef 被跨行分割,上述方法仍然有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 2019-04-03
      • 1970-01-01
      • 1970-01-01
      • 2012-05-26
      • 2015-02-06
      • 1970-01-01
      相关资源
      最近更新 更多