3

我想使用 awk 在匹配的字符串中搜索字符串。但是我发现的 awk指南示例只使用了一个匹配项,或者听起来很有希望的 SO 问题的答案非常具体,以至于我无法轻易地从中得出一般原则来解决我的问题。

例如,我想从cat /proc/bus/input/devices带有如下文本的命令中获取“Thinkpad Extra Buttons”设备的事件处理程序编号:

I: Bus=0011 Vendor=0001 Product=0001 Version=ab54
N: Name="AT Translated Set 2 keyboard"
H: Handlers=sysrq kbd event3 
B: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe

I: Bus=0019 Vendor=17aa Product=5054 Version=4101
N: Name="ThinkPad Extra Buttons"
P: Phys=thinkpad_acpi/input0
H: Handlers=rfkill kbd event7 
B: KEY=18040000 0 10000000000000 0 101501b00102004 8000000001104000 e000000000000 0

I: Bus=0003 Vendor=04f2 Product=b2ea Version=0518
N: Name="Integrated Camera"
P: Phys=usb-0000:00:1a.0-1.6/button

产生看起来像的输出

H: Handlers=rfkill kbd event7

使用记录范围模式,我可以只提取“Thinkpad Extra Buttons”块,然后尝试添加另一个搜索模式,如下所示:

cat /proc/bus/input/devices | awk '/Think/,/event/ {print}; /event/ {print $2} 

我得到了所有不相关的 Handlers 行,而不仅仅是“Thinkpad Extra Buttons”的行

Handlers=event0
Handlers=kbd
Handlers=kbd
Handlers=sysrq
N: Name="ThinkPad Extra Buttons"
P: Phys=thinkpad_acpi/input0
S: Sysfs=/devices/platform/thinkpad_acpi/input/input7
U: Uniq=
H: Handlers=rfkill kbd event7 
Handlers=rfkill
Handlers=kbd
Handlers=event9
Handlers=event10

我意识到我可以将该范围模式的结果通过管道传输到单独的 awk 命令中并在 H: Handlers 行上进行搜索。但是,当我想查找多个 Thinkpad 命名设备时,这不起作用,但实际上 awk 似乎应该能够做这种事情,但它让我感到困扰,我还没有弄清楚。

4

4 回答 4

6

这种问题很适合逐段处理,而不是逐行处理。使用 GNU awk:

gawk -v RS='' '
    /N:.*ThinkPad Extra Buttons/ {
        match($0, /(H:.*event[0-9]+)/, a)
        print a[0]
        exit
    }
' /proc/bus/input/devices

如果您愿意超越 awk:

perl -00 -lne 'if (/^N: Name=.ThinkPad Extra Buttons/m) {print /^(H:.*)$/m; exit}' /proc/bus/input/devices
于 2013-03-19T20:57:13.057 回答
3

这是一个可能对您有用的快速解决方案:

awk '
/^N: Name="ThinkPad Extra Buttons"$/ { found = 1; }
/^H: Handlers=/ { handlers = $0; }
$0 == "" { endRecord(); }
END { endRecord(); }
function endRecord() {
    if (found) {
        print handlers;
        found = 0;
    }
}
' file.txt

这是做什么的:

  • 准确地查找“ThinkPad”行,用它来标记您正在查看您关心的记录。

  • 注意所有“H”处理程序行的内容。

  • 在每个“记录”的末尾打印出处理程序行,其中每个“记录”由空行分隔。(注意:这不是 Awk 记录;就 Awk 而言,每一行都是一条记录。)

于 2013-03-19T18:41:47.660 回答
1

上述两个答案都有效,但它一直在咬我,应该有一个超短的方法来做到这一点。

这就是我想出的:

awk '/Think/,/event/ {if(/event/) {print $4}}' /proc/bus/input/devices

这背后的原理是它在一个范围内匹配,然后在第一组花括号内,我可以对那些捕获的行进行逐行处理。

于 2013-03-21T17:09:57.387 回答
0

这可以像下面这样实现.... 1) 假设我有以下排序的输出,我需要使用 awk 对其进行处理。

$ grep mouse /proc/bus/input/devices
N: Name="Macintosh mouse button emulation"
H: Handlers=mouse0 event1
H: Handlers=mouse1 event3




   $ awk '/Macintosh /,/event/ {if(/event/) {print $2,$3}}' /proc/bus/input/devices
    Handlers=mouse0 event1

下面对我不起作用...

$ awk '/Macintosh /,/event/ {if(/event/) {print $4}}' /proc/bus/input/devices
于 2016-04-20T08:54:10.347 回答