我想使用awk在匹配的字符串中搜索字符串。但我发现awk guides和examples只使用了一个匹配,或者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应该能够做到这一点,并且它让我觉得我还没想到它。
答案 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