我有一个场景,我需要打印一行,但是如果使用 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.
您需要使用
~
二元运算符,其语法为:要将字符串与正则表达式匹配,因此:
打印第三个字段与扩展正则表达式匹配的记录(默认操作的
{print}
缩写)。{print $0}
^37:[[:digit:]]+$
在 ERE 语法中:
^
在主题的开头匹配[...]
: 匹配集合中的任何字符或排序元素。[:digit:]
在上面的集合中表示在区域设置中分类为十进制数字的任何字符(在大多数系统上,仅限于 0123456789)。更改为0123456789
inmawk
which 不支持那些 POSIX 字符类,或者如果您不想匹配其他十进制数字。0-9
也可以工作,mawk
但也可以在某些awk
实现中匹配其他字符。+
是针对前面的一个或多个。所以这里有一个或多个数字$
匹配在主题的末尾。如果您不关心后面的部分
37:
是否由数字组成,那么正则表达式只是^37:
(37:
在主题的开头)。另一种方法是:
数字
+ 0
运算强制awk
尝试转换$3
为数字,忽略初始数字之后的任何内容。然后这将匹配37:anything
,但也匹配37.0;whatever
¹,3.7e+1
¹,可能0x25#xxx
与某些awk
实现,+37+38
...+$3 == 37
虽然使用标准,但不适用于某些awk
实现。37
对于来自 shell 变量的值(此处),您可以在 shell 中构造正则表达式并awk
通过ENVIRON
ment 变量将其传递给:或者
awk
v
从 shell 变量中创建一个变量²:避免将 shell 变量扩展到
awk
代码中,如下所示:因为这通常会引入命令注入漏洞(最严重的漏洞类型)。
对您的尝试的一些评论:
$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
它也可以自己打开它。¹假设十进制基数字符在语言环境中
.
而不是,
在语言环境中,至少对于某些awk
实现,例如awk
POSIX 模式下的 GNU。² 请注意会
-v
破坏反斜杠,因此ENVIRON
在一般情况下使用更安全。第一个错误是
"
对awk
脚本使用双引号,这使得 shell 扩展$3
为 shell 所具有的任何内容,这里大概是空字符串。请改用单引号'
或文件。然后,当然,为您的任务使用正确的正则表达式,如其他答案中所述。