Regex grep中方括号内的字符分组

Regex grep中方括号内的字符分组,regex,grep,Regex,Grep,我有一个名为区域文件的文件,内容如下: c3-Tx-Msi-US IN CNAME c3-L123-Tx-Msi-US c3-L123-Tx-Msi-US IN A 192.0.2.11 c5-Ny-Msi-US IN CNAME c5-L123-Ny-Msi-US c5-L123-Ny-Msi-US IN A 192.0.2.33 c1-Ny-Gre-SE IN CN

我有一个名为
区域文件
的文件,内容如下:

c3-Tx-Msi-US         IN      CNAME   c3-L123-Tx-Msi-US
c3-L123-Tx-Msi-US  IN      A       192.0.2.11
c5-Ny-Msi-US         IN      CNAME   c5-L123-Ny-Msi-US
c5-L123-Ny-Msi-US  IN      A       192.0.2.33
c1-Ny-Gre-SE      IN      CNAME    c1-L123-Ny-Gre-SE
c1-L123-Ny-Gre-SE    IN       A     192.0.2.89
r6-Ms-Msi-UK         IN      CNAME   r6-L123-Ms-Msi-UK
r6-L123-Ms-Msi-UK  IN      A       192.0.2.16
c1-St-Rec-SE      IN      CNAME    c1-L123-St-Rec-SE
c1-L123-St-Rec-SE    IN       A     192.0.2.1
我想把
c3-Tx-Msi-US
c5-Ny-Msi-US
r6-Ms-Msi-UK
。这意味着正则表达式必须包含此
Msi
字符串,grep命令的输出应如下所示:

c3-Tx-Msi-US
c5-Ny-Msi-US
r6-Ms-Msi-UK

我想用尽可能松散的正则表达式来完成这一点,这意味着搜索除空格或制表符之外的任何字符,直到字符串
Msi
,然后再搜索除空格或制表符之外的一个或多个字符。因此
grep-Po“^[^\t]+Msi[^\t]+”区域文件
将是完美的,但这也包括
c3-L123-Tx-Msi-US
c5-L123-Ny-Msi-US
r6-L123-Ms-Msi-UK
。是否可以将字符分组到方括号内?我的意思是像
grep-Po“^[^\t'L123']+Msi[^\t]+”区域文件
?看起来这是不可能的?

对于您的示例,这将完成以下工作:

grep CNAME zone-file | cut -d' ' -f1

这使用GNU grep中与Perl兼容的正则表达式引擎。它找到一个包含字符串Msi的“单词”,其中CNAME稍后出现在同一行中。
-o
选项将输出限制为仅匹配文本。

或使用awk:
awk'/CNAME/{print$1}'区域文件
是或使用[]+CNAME.*/\1/'-E'/A/d'区域文件中的sed
sed-E-E/(*)。如果这是高尔夫,你就赢了。谢谢回复!我在最初的帖子中没有提到这个区域文件还有其他CNAME条目。对不起,我弄错了。这意味着正则表达式必须包含这个“Msi”字符串。此外,如果可能的话,我更喜欢
grep
。@martin,你必须在问题中提出所有要求:不要让那些想帮助你的人阅读所有其他答案中的所有评论。谢谢,这非常有效!但是,请您解释一下“\S*(?=.*CNAME)”部分。据我所知,您将零个或多个空格(空格、制表符、换行符)字符与
\S*
匹配,
*CNAME
应该表示零个或多个后跟单词CNAME的字符,但是
(?=)
的意思是什么?请注意,这
\S
是大写的。对于perl正则表达式,这意味着“非空白”字符。所以
\S+Msi\S*
是一个包含“Msi”的非空白字符序列。
(?=.*CNAME)
部分是一个“向前看”断言,意思是“从我在字符串中的当前位置来看,模式是否匹配接下来的内容”
grep -oP '\S+Msi\S*(?=.*CNAME)'