awk reg表达式匹配不起作用

时间:2015-07-26 15:24:23

标签: regex shell awk

我尝试使用[:digit:]来匹配行中的数字,这是代码。

~ echo -e "abc\n123\ndef" | awk '{/[[:digit:]]/{print $0}}'
awk: syntax error at source line 1
 context is
     >>> {/[[:digit:]]/{ <<<
awk: illegal statement at source line 1
awk: illegal statement at source line 1

我的问题是:

1,为什么要使用[[:digit:]]代替[:digit:]

2,为什么这段代码片段无法运行?如何修改它?

2 个答案:

答案 0 :(得分:2)

你不能把你的图案放在大括号内。

awk '/[[:digit:]]/{print $0}'

语法将是,

 awk 'condition{execute if the condition is true}'

在某些情况下,单独使用条件就足够了。对于这种情况,下面就足够了,

awk '/[[:digit:]]/'

示例:

$ echo -e "abc\n123\ndef" | awk '/[[:digit:]]/'
123
  

为什么使用[[:digit:]]代替[:digit:]

单独的POSIX括号表达式[:digit:]与数字字符不匹配,您必须将其放在像[[:digit:]]这样的字符类中。

如果你想匹配数字以及+符号,你可以修改上面的POSIX类

[+[:digit:]]

答案 1 :(得分:2)

Awk语法是:

<condition> { <action> }

如果<action>对于当前记录为真,则执行<condition>。你写的是:

{ <condition> { <action> } }

看到区别?你可以在一个动作块中添加一个条件,但是你需要用适当的控制关键字(如ifwhile来包围它,这样awk会知道你想对这个条件做什么:

{ if (<condition>) { <action> } }
{ while (<condition>) { <action> } }

所以,而不是:

{/[[:digit:]]/{print $0}}

在语法和惯用方面你应该写的:

/[[:digit:]]/{print $0}

但是因为打印$ 0是默认操作,所以你真正写的是:

/[[:digit:]]/

即:

$ echo -e "abc\n123\ndef" | awk '/[[:digit:]]/'
123

至于为什么[[:digit:]]而不是[:digit:]

[:digit:]是一个POSIX字符类,因此可以在括号表达式中用作正则表达式的一部分,例如[[:digit:]],就像范围表达式(0-9)或字符列表(0123456789)一样,也可以在括号表达式中使用,以达到相同的效果。

这个例子可能有助于澄清:[:digit:]是一个字符类,因此是[:punct:]所以[[:digit:][:punct:] \t]是一个括号表达式,包含2个字符类和一个字符列表({{1} })。

来自POSIX(http://pubs.opengroup.org/onlinepubs/9699919799/toc.htm):

  

字符类表达式表示为字符类名称   括在括号内 - (“[:”和“:]”)分隔符。

  

括号表达式(用方括号括起来的表达式,“[]”   )...是匹配列表表达式或不匹配列表   表达。它由一个或多个表达式组成:...,字符   课程,.....

因此,字符类为\t,括号表达式为[:<name>:],其中[<expression>]可以/包含字符类:<expression>

P.S。警告:有一个常用的网站http://www.regular-expressions.info/posixbrackets.html,其字符类和括号表达式的术语完全错误。或者更公平地说,他们使用的术语充其量是模糊的,因为他们将POSIX括号表达式称为“字符类”,但他们也将POSIX字符类称为“字符类”。无论你想要表征它,因为它们在自己的网站上陈述自己,它们的术语肯定不是POSIX用于括号表达式和字符类的术语