使用grep linux命令和perl regex +捕获组

时间:2014-07-10 01:06:25

标签: regex linux perl

所以我对这个问题进行了一些研究,但我并没有找到完美的解决方案。 例如,我在变量中有一个字符串。

var="a1b1c2"

现在我想要做的只是匹配" a"按照任何数字,但我只希望它返回" a"之后的数字。 要匹配一个规则,如

'a\d'

因为我只需要数字,所以我尝试了

'a(\d)'

也许它确实捕捉到了某个地方,但我不知道在哪里,这里的输出仍然是" a1"

我还尝试过一个非捕获组来忽略" a"在输出中,但在perl正则表达式中没有效果:

'(?:a)\d'

供参考,这是我的终端中的完整命令:

[root@host ~]# var="a1b1c2"
[root@host ~]# echo $var |grep -oP "a(\d)"
a1 <--output

也可能没有-P(一些非perl正则表达式格式),我感谢你的每一个答案:)

修改 使用

\K

不是真正的解决方案,因为我不一定需要比赛的最后部分。

EDIT2: 我需要能够获得比赛的任何部分,例如:

[root@host ~]# var="a1b1c2"
[root@host ~]# echo $var |grep -oP "(a)\d"
a1 <--output
but the wanted output in this case would be "a"

EDIT3: 使用&#34;后视断言&#34;几乎解决了这个问题。如:

(?<=a)\d

不会返回字母&#34; a&#34;,只返回它后面的数字,但它需要一个固定的长度,例如它不能用作:

(?<=\w+)\d

EDIT4: 到目前为止,最好的方法是使用perl或结合使用后视断言和\ K但它仍然有一些限制。例如:

1234_foo_1234_bar
1234567_foo_123456789_bar
1_foo_12345_bar

if "foo" and "bar" are place-holders for words that don't always have the same length,
there is no way to match all above examples while output "foobar", since the
number between them doesn't have a fixed length, while it can't be done with \K since we need "foo"

仍然赞赏任何进一步的建议:)

3 个答案:

答案 0 :(得分:18)

  

经过一些测试后我发现,后视断言中的模式需要固定长度(像(?<=\w+)something这样的东西不起作用,有什么建议吗?

我之前发布并删除了我的回答,因为您说它不符合您的需求:

大部分时间,可以使用\K来避免可变长度的后视镜。这会重置报告的匹配的起点,并且不再包括任何以前消耗的字符。 (抛弃与此相匹配的所有内容。

使用\K和lookbehind之间的主要区别在于,lookbehind不允许使用量词:您要查找的长度必须固定。但是\K可以放在模式中的任何位置,因此您可以使用任何量词。

正如您在下面的示例中所看到的,在lookbheind中使用量词将无效。

echo 'foosomething' | grep -Po '(?<=\w+)something'
#=> grep: lookbehind assertion is not fixed length

所以你可以这样做:

echo 'foosomething' | grep -Po '\w+\Ksomething'
#=> something

要仅在两个模式之间获取子字符串,您可以将Positive Lookahead添加到混合中。

echo 'foosomethingbar' | grep -Po 'foo\K.*?(?=bar)'
#=> something

或使用固定的Lookbehind与Lookahead结合使用。

echo 'foosomethingbar' | grep -Po '(?<=foo).*?(?=bar)'
#=> something

答案 1 :(得分:2)

模式(?<=a)\d使用后视断言仅打印字母&#39; a&#39;后面的数字。这适用于GNU grep -Poack -opcregrep -o。断言为零宽度,因此不包含在匹配中。

答案 2 :(得分:1)

您可以直接使用Perl,通过%ENV哈希访问环境变量:

perl -lwe 'print $ENV{var} =~ /a(\d+)/;'

它只会在括号内打印捕获。