我正在编写一个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" )
为了清楚起见,我希望所有组按顺序输出 。
在这个上撕掉我的头发。所有帮助表示赞赏。
答案 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
# ...
}'