xev | awk -F'[ )]+' '/^KeyPress/ { a[NR+2] } NR in a { printf "%-3s %s\n", %5, %8}
当我使用 xev 时,我只需要某些信息。使用 xev 获取密钥代码信息的自然响应如下所示......
KeyPress event, serial 48, synthetic NO, window 0x1600001,
root 0xf6, subw 0x0, time 754405, (348,566), root:(349,620),
state 0x0, keycode 40 (keysym 0x64, d), same_screen YES,
XLookupString gives 1 bytes: (64) "d"
XmbLookupString gives 1 bytes: (64) "d"
XFilterEvent returns: False
KeyRelease event, serial 48, synthetic NO, window 0x1600001,
root 0xf6, subw 0x0, time 754488, (348,566), root:(349,620),
state 0x0, keycode 40 (keysym 0x64, d), same_screen YES,
XLookupString gives 1 bytes: (64) "d"
XFilterEvent returns: False
AWK 脚本的结果只会返回:
40 d
这让我想学习 AWK :)
因此,在学习了 NR 并做了一些教程之后,我现在正在尝试解决这个问题。首先 -F 只是除以本例中的字段 '[ )]+' 我认为这是 1 个或多个空格或右括号的正则表达式。我不明白。我在前置词之前没有看到任何空格。另外,我不知道正则表达式框中的空格在这里有什么作用,因为我只了解了诸如 \s 之类的空白工具。所以我想看看哪些字段显示 $5 和 %8,因为它在我的分析中看起来不正确,我很困惑!
echo "state 0x0, keycode 12 (keysym 0x33, 3), same_screen YES," | awk '{print $8}'
same_screen
echo "state 0x0, keycode 12 (keysym 0x33, 3), same_screen YES," | awk '{print $5}'
(keysym
编辑:所以这是什么 printf "%-3s %s\n", $5, $8}
?为什么输出与上面的 echo 示例如此不同?
显然,这是来自于魔法{a[NR+2] NR in a}
。某种数组和 for 循环。
我看着 NR+2,它让我想到:因为当 AWK 启动时,NR 从 1 开始,加上 2 就会使其成为第三行。这看起来是正确的,因为我想要的所有信息都在第三行。
a[NR+2] 是怎么回事?对于 printf 中的 NR...?我了解 printf 我了解 for 循环。这里使用 NR 的方式让我感到困惑。
我想真正的问题是“a”发生了什么?这是我不知道的预定义的事情吗?
答案1
你似乎已经正确地推断{a[NR+2]} NR in a { ... }}
出了什么;
/^KeyPress/ {a[NR+2]}
当行的开头与字符串匹配时,在a
带有索引的数组中创建一个(空值)元素NR+2
NR
KeyPress
NR in a
/^KeyPress/
因此对于下面两行匹配的行来说是正确的
在这方面,也许可以更透明地写为
awk -F'[ )]+' '/^KeyPress/ {n=NR+2} NR==n { printf "%-3s %s\n", $5, $8}'
一个可能更棘手的问题是为什么要打印的字段是$5
and$8
而不是$4
and $7
;这是因为使用非默认字段分隔符时,初始空格的处理方式有所不同:默认字段分割GNUawk
手册的部分:
字段通常由空白序列(空格、制表符和换行符)分隔,而不是由单个空格分隔。一行中的两个空格不会界定空字段。字段分隔符 FS 的默认值是包含单个空格“”的字符串。如果 awk 以通常的方式解释该值,则每个空格字符将分隔字段,因此一行中的两个空格将在它们之间形成一个空字段。之所以不会发生这种情况,是因为单个空格作为 FS 的值是一种特殊情况——它用于指定分隔字段的默认方式。
如果 FS 是任何其他单个字符,例如“,”,则该字符的每次出现都会分隔两个字段。连续两次出现界定一个空字段。如果该字符出现在行的开头或结尾,那么也会界定一个空字段。空格字符是唯一不遵循这些规则的单个字符。
答案2
%-3s
表示在 3 个字符宽的字段中打印字符串,并在右侧而不是左侧填充空格。所以它会打印
40 d
而不是
40 d
答案3
我可以提供一些帮助,但这里的某人应该能够提供更深入的答案。但是,让我们分解一下。
首先,您使用 | 将 xev 的输出通过管道传输到 awk 中。
您是正确的,-F 正在定义 Awk 的列分隔符,并且匹配该字符的正则表达式是 [ )]+
它只会在您提供的示例输出中匹配一次。之后的一切都是 awk 脚本。
/^KeyPress/ 是另一个正则表达式,寻找以“KeyPress”开头的换行符...这似乎多余。
printf 的参数以逗号分隔,第一个参数是格式,因此:“%-3s %s\n”是格式。参见和这里
{printf "%-3s %s\n", %5, %8} 是否有可能是 { printf "%-3s %s\n", $5, $8} ?
我不太明白这一点。希望其他人可以解码它!顺便说一句-你可以使用这帮助测试正则表达式。