【问题标题】:using grep linux command with perl regex + capturing groups使用 grep linux 命令和 perl 正则表达式 + 捕获组
【发布时间】:2014-08-31 04:56:17
【问题描述】:

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

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: 使用“look-behind assertions”几乎可以解决该问题,例如:

(?<=a)\d

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

(?<=\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"

任何进一步的建议仍然很感激:)

【问题讨论】:

    标签: regex linux perl


    【解决方案1】:

    经过一些测试,我发现后视断言中的模式需要固定长度((?&lt;=\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
    

    【讨论】:

    • 非常感谢您的帮助,请不要误会我的意思,但是如何匹配“foosomethingbar”同时只返回“foo”和“bar”之间的所有内容而“something " 是什么,但 "bar" - 'foo(.*)bar'?感谢您的帮助。
    • 谢谢!结合后视断言和 \K 扩展了很多可用性,我应该能够匹配我现在需要的任何东西。即使没有简单的方法来捕捉特定的部分,这个也不错。
    • +1 对一个问题的史诗般的工作,该问题一开始是需要一个单行答案的问题。
    【解决方案2】:

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

    【讨论】:

    • 经过一些测试,我发现,后视断言中的模式需要固定长度(像'(?
    【解决方案3】:

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

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

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

    【讨论】:

    • 这解决了我的问题,感谢和抱歉可能存在的任何误解。如果有的话,我也愿意接受 grep 解决方案(没有 for 循环)。
    猜你喜欢
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 1970-01-01
    • 2018-08-30
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    相关资源
    最近更新 更多