用perl正则expression式+捕获组使用grep linux命令

所以我已经做了一些关于这个问题的研究,但是我没有find完美的解决scheme。 例如,我有一个variables内的string。

var="a1b1c2" 

现在我想要做的只是匹配任何数字后跟一个“a”,但我只希望它返回“a”之后的数字为了匹配它的规则,如

 'a\d' 

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

 'a(\d)' 

也许它确实捕捉到了某处,但是我不知道在哪里,这里的输出仍然是“a1”

我也尝试了一个非捕获组来忽略输出中的“a”,但在perl regex中没有效果:

 '(?:a)\d' 

作为参考,这是我的terminal中的完整命令:

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

也许这也可能没有-P(一些非Perl的正则expression式格式),我感谢每一个答案:)

编辑:使用

 \K 

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

编辑2:我需要能够得到比赛的任何部分,例如:

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

编辑3:问题几乎解决使用“后视断言”,如:

 (?<=a)\d 

将不会返回字母“a”,只有后面的数字,但它需要一个固定的长度,例如它不能被用作:

 (?<=\w+)\d 

编辑4:到目前为止最好的方法是使用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" 

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

经过一些测试后,我发现,在后视断言内部的模式需要固定的长度(类似(?<=\w+)something不会工作,有什么建议吗?

正如我以前发布和删除我的答案,因为你说它不符合你的需要:

大多数情况下,通过使用\K 可以避免可变长度的向后看 。 这将重置报告匹配的起始点,并且不再包含任何以前消耗的字符。 ( 抛弃与之相配的所有东西

使用\K和一个倒序之间的关键区别是,倒序不允许使用量词:你正在寻找的长度必须是固定的 。 但是\K可以放在任何模式的任何地方,所以你可以使用任何量词。

正如你在下面的例子中看到的,在lookbheind中使用量词是行不通的。

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

所以你可以这样做:

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

为了只在两种模式之间获得一个子字符串,你可以添加积极的Lookahead到混合中。

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

或者使用了固定的Lookbehind和Lookahead。

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

模式(?<=a)\d使用后退断言来仅打印字母“a”后面的数字。 这适用于GNU grep -Poack -opcregrep -o 。 断言是零宽度,所以它不包括在比赛中。

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

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

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