如何在 awk if 语句中使用星号

如何在 awk if 语句中使用星号

我有一个场景,我需要打印一行,但使用 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 字符类。也可以工作,但也可以在某些实现中匹配其他字符。mawk0-9mawkawk
  • +是针对前面的一个或多个事物。所以这里是一位或多位数字
  • $匹配主题末尾。

如果您不关心后面的部分是否37:由数字组成,那么正则表达式只是^37:(37:在主题的开头)。

另一种方法是:

<test_out.txt awk '$3 + 0 == 37'

+ 0数字运算强制尝试awk转换$3为数字,忽略初始数字之后的任何内容。然后,这将匹配37:anything,但也匹配37.0;whatever1, 3.7e+11,可能0x25#xxx与某些awk实现相匹配,+37+38...+$3 == 37尽管使用标准,但不适用于某些awk实现。

37对于来自 shell 变量的值(此处),您可以在 shell 中构造正则表达式并awk通过ENVIRONment 变量将其传递给:

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实现(例如awkPOSIX 模式下的 GNU)而言是这样。

² 请注意-v反斜杠的损坏,因此ENVIRON在一般情况下使用更安全。

答案2

"第一个错误是在脚本中使用双引号awk,这使得 shell 扩展$3为 shell 所具有的任何内容,这里可能是空字符串。请改用单引号'或文件。

然后,当然,请使用正确的正则表达式来完成您的任务,如其他答案中所示。

相关内容