grep输出所有捕获组,晚上没有匹配

时间:2014-02-12 16:18:27

标签: regex bash shell awk

我正在编写一个bash脚本,我正在使用带有正则表达式的grep用于某些DNS记录,我有4个捕获组,第二个是可选的

是否可以获得这些输出,以便始终为五个组,并且每次都有相同的顺序。

正则表达式我正在使用grep -Eo

^([a-z0-9@\-\.\*]+?)\s+(?:([0-9]*)\s)?([A-Z]*)\s*(.*)$

要匹配的内容:

www    43200 A 1.2.3.4
t        CNAME s.test.com.
blog             A 4.3.2.1
@                   MX 20 cluster3a.eu.messagelabs.com.
@                   TXT ( "some text" )

当输入awk之类的内容时,我希望每行的输出如下

$1 = www , $2 = 43200 , $3 = A , $4 = 1.2.3.4
$1 = t , $2 = , $3 = CNAME , $4 = s.test.com.
$1 = @ , $2 = , $3 = MX , $4 = MX 20 cluster3a.eu.messagelabs.com.
$1 = @ , $2 = , $3 = TXT , $4 = ( "some text" )

为了清楚起见,我希望所有组按顺序输出

在这个上撕掉我的头发。所有帮助表示赞赏。

1 个答案:

答案 0 :(得分:4)

您似乎使用的是perl风格的正则表达式,它不适用于grep -E(您需要grep -P,这是非标准的,但与gnu grep配合使用),并且还赢了通常与awk一起使用。幸运的是,您不需要任何扩展。

这是一个简单的正则表达式,它将以awk格式运行,只有四个捕获:

/^([a-z0-9*@.-]+)[[:blank:]]+([0-9]*)[[:blank:]]*([A-Z]+)[[:blank:]]*(.*)/

您可以按如下方式使用它(但仅限于Gnu awk:match的三参数版本是Gnu扩展名):

awk '{match($0,
            /^([a-z0-9*@.-]+)[[:blank:]]+([0-9]*)[[:blank:]]*([A-Z]+)[[:blank:]]*(.*)/,
            field);
      print "<" field[1] "> <" field[2] "> <" field[3] "> <" field[4] ">";
     }' \
<<<'www    43200 A 1.2.3.4
t        CNAME s.test.com.
blog             A 4.3.2.1
@                   MX 20 cluster3a.eu.messagelabs.com.
@                   TXT ( "some text" )'

输出:

<www> <43200> <A> <1.2.3.4>
<t> <> <CNAME> <s.test.com.>
<blog> <> <A> <4.3.2.1>
<@> <> <MX> <20 cluster3a.eu.messagelabs.com.>
<@> <> <TXT> <( "some text" )>

但是,使用awk自己的行分割工具可能更简单:

awk '{  if ($2~/^[[:digit:]]+$/) { ttl=$2; type=$3; arg=4; }
       else                     { ttl=0;  type=$2; arg=3; }
       name=$1
       args=$arg
       for (++arg;arg<=NF;++arg) args=args " " $arg                   
       # ...
     }'