使用一个awk命令在匹配的字符串中搜索字符串

时间:2013-03-19 18:00:06

标签: awk

我想使用awk在匹配的字符串中搜索字符串。但我发现awk guidesexamples只使用了一个匹配,或者promising sounding SO questions有答案specific,我不能轻易地从他们那里得到一般原则来解决我的问题。

例如,我想从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

使用record range patterns我只能抓取“Thinkpad Extra Buttons”块,但之后尝试添加另一个搜索模式:

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

我获得了所有不相关的处理程序行,而不仅仅是“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 个答案:

答案 0 :(得分: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

答案 1 :(得分: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而言,每一行都是记录。)

答案 2 :(得分:1)

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

这就是我提出的:

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

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

答案 3 :(得分: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