我有一个场景,我需要打印一行,但使用 awk 如果要搜索一个数字,则附加一个带有更多数字的双冒号:
请参见下面的示例:
test1 test2 37:375003 test3 test4
test1 test2 38:375004 test3 test4
test1 test2 39:375005 test3 test4
test1 test2 40:375006 test3 test4
test1 test2 41:375007 test3 test4
我想要实现的是使用如下命令:
cat test_out.txt | awk "{if ($3 == 37~/\:*/ ) print $0;}"
上面应该给我以下行:
test1 test2 37:375003 test3 test4
得到下面的语法错误:
Syntax Error The source line is 1.
The error context is
{if ( >>> == <<<
awk: 0602-502 The statement cannot be correctly parsed. The source line is 1.
答案1
您需要使用~
二元运算符,其语法为:
string ~ regexp
要将字符串与正则表达式匹配,请执行以下操作:
<test_out.txt awk '$3 ~ /^37:[[:digit:]]+$/'
打印第三个字段与扩展正则表达式匹配的记录(默认操作的{print}
缩写) 。{print $0}
^37:[[:digit:]]+$
在 ERE 语法中:
^
匹配主题的开头[...]
:匹配集合中的任何字符或整理元素。[:digit:]
上面的集中表示在区域设置中分类为十进制数字的任何字符(在大多数系统上,仅限于 0123456789)。如果您不想匹配其他十进制数字,请更改为0123456789
其中不支持这些 POSIX 字符类。也可以工作,但也可以在某些实现中匹配其他字符。mawk
0-9
mawk
awk
+
是针对前面的一个或多个事物。所以这里是一位或多位数字$
匹配主题末尾。
如果您不关心后面的部分是否37:
由数字组成,那么正则表达式只是^37:
(37:
在主题的开头)。
另一种方法是:
<test_out.txt awk '$3 + 0 == 37'
+ 0
数字运算强制尝试awk
转换$3
为数字,忽略初始数字之后的任何内容。然后,这将匹配37:anything
,但也匹配37.0;whatever
1, 3.7e+1
1,可能0x25#xxx
与某些awk
实现相匹配,+37+38
...+$3 == 37
尽管使用标准,但不适用于某些awk
实现。
37
对于来自 shell 变量的值(此处),您可以在 shell 中构造正则表达式并awk
通过ENVIRON
ment 变量将其传递给:
var=37
ERE='^'$var':[[:digit:]]+$' <test_out.txt awk '$3 ~ ENVIRON["ERE"]'
或者awk
v
从 shell 变量中创建一个变量²:
var=37
<test_out.txt awk -v n="$var" '$3 ~ "^" n ":[[:digit:]]+"'
避免将 shell 变量扩展到awk
代码中,如下所示:
<test_out.txt awk '$3 ~ /^'"$var"':[[:digit:]]+$/'
因为这通常会引入命令注入漏洞(最糟糕的漏洞类型)。
对您的尝试的一些评论:
- 已经一样由@RudyC 指出,您在 awk 代码周围使用了双引号。 Shell 在其中执行参数扩展,因此
$3
将扩展为 shell 脚本的第三个参数的值以及$0
脚本的名称。 $3 == 37 ~ /\:*/
。==
优先级高于~
。所以那是($3 == 37) ~ /\:*/
。这就是将\:*
正则表达式与比较结果进行匹配(1 或 0 取决于是否$3
为 37)\:*
因为正则表达式未指定,所以\:
未指定。为了匹配文字:
,它是:
单独的。:*
将是 0 或多个:
s,因此可以匹配任何内容,因为任何字符串都至少包含 0:
s。*
在正则表达式中匹配 0 个或多个前一个事物。您可能会将其与*
匹配 0 个或多个字符的 shell 通配符混淆。在正则表达式中,0 个或多个字符是.*
,.
是匹配单个字符的运算符。awk
语句的形式为condition {action}
, 其中状况或者行动可以省略。就您而言,您省略了状况并if
用于行动,并使用{print $0}
恰好是默认值的行动。虽然这有效,但对用户来说会显得非常awk
不友好awk
。- 您曾经
cat
连接cat
一个文件,这几乎没有意义。 shell 可以自行打开文件,使其成为awk
使用重定向的标准输入,从而节省了进程以及通过管道推送内容的需要。您还可以将文件名作为参数传递给它,awk
该文件也可以自行打开。
1 假设十进制基数字符在语言环境中.
且不,
在语言环境中,至少对于某些awk
实现(例如awk
POSIX 模式下的 GNU)而言是这样。
² 请注意-v
反斜杠的损坏,因此ENVIRON
在一般情况下使用更安全。
答案2
"
第一个错误是在脚本中使用双引号awk
,这使得 shell 扩展$3
为 shell 所具有的任何内容,这里可能是空字符串。请改用单引号'
或文件。
然后,当然,请使用正确的正则表达式来完成您的任务,如其他答案中所示。