管道sed | awk 或 awk | sed

Posted

技术标签:

【中文标题】管道sed | awk 或 awk | sed【英文标题】:piping sed | awk or awk | sed 【发布时间】:2017-04-23 02:54:16 【问题描述】:

我绝对可以被视为 sed/awk 新手。我一直在努力做一个多步过滤器,但没有成功。每个部分单独运行时都会产生结果,但是当我将它们链接在一起时,我什么也得不到。我试过 sed|awk、awk|sed、sed|sed、awk|awk。他们都失败了,所以我假设这是除了我以外的所有人都知道的事情。

数据是多行文本块,其中每个块都可以视为一条记录(因此使用“>”分隔符)。在我们过滤到 ADV_NONCONN 块之后,我想将文本块过滤到仅包含“bdaddr”或“RSSI”的行。据我所知,我需要通过管道进入一个单独的操作来执行此操作。

sudo hcidump | awk 'BEGIN RS=">" /ADV_NONCONN/' | sed -n -e "/bdaddr/p" -e "/RSSI/p" > log.txt

hcidump 输出样本(一个“记录”):

HCI Event: LE Meta Event (0x3e) plen 43
    LE Advertising Report
      ADV_NONCONN_IND - Non connectable undirected advertising (3)
      bdaddr 0C:F3:EE:0D:70:89 (Public)
      Flags: 0x06
      Unknown type 0xff with 26 bytes data
      RSSI: -62

运行逆向(首先是 sed 部分,然后是 awk)会给出相同的空集结果。我错过了什么简单的事情?

【问题讨论】:

几乎没有必要将awk 传递给sed,因为awk 可以做sed 可以做的大部分事情,而且awk 语法通常更容易理解。 请允许我给您一些反馈:您的问题和您自己的回答都非常健谈,以至于分心 - 请考虑让它们更简洁和集中。 另外,给新手的一些标准建议:如果一个答案解决了您的问题,请点击旁边的大复选标记 (✓) 接受它,也可以选择投票(需要投票)至少 15 个声望点)。如果您发现其他答案有帮助,请给他们投票。接受和投票有助于未来的读者。请参阅the relevant help-center article。如果您的问题尚未完全得到解答,请提供反馈。如果您认为自己找到了最佳解决方案,请将其发布为答案并自我接受。 【参考方案1】:

无需将awk 传递给sed。只需在awk 命令中添加附加条件:

sudo hcidump | awk -v RS=">" '/ADV_NONCONN/ 
    n = split($0, line, /\n/);
    for (i = 1; i <= n; i++) 
        if (line[i] ~ /bdaddr|RSSI/) print line[i];
    
' > log.txt

【讨论】:

我想我错过了一些细节(我会添加到原始问题)。 awk 处理的每个记录都是一个多行文本块。在 awk 过滤到包含 ADV_NONCONN 的记录之后,我需要只过滤到该记录块中包含 bdaddr 或 RSSI 的行。你的 awk sn-p 也给了我空集。 我已经对其进行了修改,以遍历 awk 块中的行。 但我承认现在这并不像您最初的尝试那么简单,我不确定为什么它不起作用。 就是这样。谢谢。我仍然不确定为什么我不能通过管道输出 awk 的输出,然后用 sed 处理它,但至少在这种情况下它并不重要。干杯。 你不需要使用split()来创建数组,只需设置-F'\n'并在字段上循环。【参考方案2】:

好的,所以我最终想通了。我相信 awk 输出不是非常可管道化的,因为它对输入流进行了某种缓冲/不关闭。从最初的问题开始,我添加了来自 hcidump 的时间戳

所以,首先我使用 sed 在时间戳之前添加一个唯一字符 (@),然后将其通过管道传输到 awk,后者使用该唯一字符 (@) 作为记录分隔符将多行视为单个记录,过滤到我想要的记录(ADV_NONCONN)然后从它读取的字段中组装适当的输出(现在包括记录头部的时间戳)。

sudo hcidump -t | sed -n '/HCI Event/s/^/@/;p' | awk 'BEGIN RS="@" -F '[\n]' /ADV_NONCONN/ print $1 " " $2 ", " $23 ", " $35' > a.txt

原始问题的解决方案是:

sudo hcidump | awk 'BEGIN RS=">" -F '[\n]' /ADV_NONCONN/ print $20 ", " $32' > a.txt

【讨论】:

以上是关于管道sed | awk 或 awk | sed的主要内容,如果未能解决你的问题,请参考以下文章

linux--补充(管道| / 重定向> / xargs)/find 与xargs结合使用/vi,grep,sed,awk(支持正则表达式的工具程序)

sed && awk

sed和awk用法

Linux sed 和 awk的用法

Linux的sed和awk

sed,awk工具学习