首页 > 解决方案 > gawk NR 和匹配问题

问题描述

我需要使用正则表达式来解析数据文件的特定行。我的带有 match 的测试命令有效,我的特定行号的测试命令有效,但是当我将它们放在一起时,我没有得到任何输出。

gawk 'NR==42 {print $0}' filename

打印出整个第 42 行

gawk 'match($0, /([0-9]+)/, a) {print NR ":" a[1]}' filename

有很多打印输出,但特别有这个输出:42:137674 所以,我的第 42 行有一个数字匹配

gawk 'NR==42 match($0, /([0-9]+)/, a) {print NR ":" a[1]}' filename

不打印任何东西,我不知道为什么。

我有一个解决方法:

gawk 'match($0, /([0-9]+)/, a) {if (NR==42) print NR ":" a[1]}' filename

但我相信它的性能较低,所以想弄清楚为什么其他命令不起作用

编辑:回答,我完全忘记了 NR 和比赛之间的 &&

标签: awk

解决方案


快速回答:问题的解决方案是添加缺少的和运算符:

NR==42 && match($0, /([0-9]+)/, a) 
 

OP中发生了什么?

awk 程序通常被编写为一组模式-动作对:

pattern { action }

actionpattern为真时执行。

上面使用的pattern内容如下:

NR==42 match($0, /([0-9]+)/, a)

由于运算符的优先顺序,实际上类似于:

NR == (42  match($0, /([0-9]+)/, a))

让我们假设,例如,我们在NR==42。match 函数返回01取决于是否找到匹配项。如 OP 中所述,match函数1NR==42. 现在pattern读到:

42 == (42 1)

形式的运算符expr expr类似于字符串连接,所以在 awk 中,它被处理为

42 == ("42" "1")
42 == "421"

当且仅当两个操作数本质上都是数字时,运算符==才是数字运算符。But"421"是一个字符串,所以它会将 的数值转换为NR字符串:

"42" == "421"

这是错误的,因此action不会执行。

注意:match当且仅当函数返回 false on line420或 true on line时,才会执行上述操作421


推荐阅读