当我在这个正则表达式中要求'A'匹配时,为什么'M'匹配?

时间:2018-01-09 18:00:04

标签: regex perl

我有这个字符串:

    A /Modules/framework/odd-core/tags

(它确实以空格开头)。我想用

来匹配它
\s+A\s+\/Modules\/\w\/\w\/branches|trunk|tags$

工作正常,但它也匹配:

    M /Modules/framework/buildtools/trunk/modules-parent/pom.xml

我特意要求它匹配角色'A',但它也会拾取角色'M'

2 个答案:

答案 0 :(得分:4)

您的正则表达式与M不匹配:它匹配trunk。你的正则表达式模式目前说:

  • 匹配以下任何模式
    • \s+A\s+\/Modules\/\w\/\w\/branches
    • trunk
    • tags$

要解决此问题,您需要将选项组合在一起,以便替换|与模式的其余部分分开。使用"非捕获组" (?: ... )工作正常。

您面临的另一个问题是使用\w字符类。它匹配集A-Za-z0-9_中的单个字符。看起来您需要匹配odd-core因为连字符-而失败,因为它不止一个字符。您需要添加到字符类并使用[\w-]+,它将匹配整个子字符串。

可以使用[^/]+(更改正则表达式的分隔符以避免转义斜杠)但是除了斜杠之外,它将匹配任何的任何字符。

正如下面评论中提到的OP问题以及我的回答,我们无法确定您的模式中\s+的用途,因为一开始就没有空格字符你的字符串。如果您的字符串实际上不包含前导空格,您可以完全删除\s+或将量词更改为*(任意数量的空格字符而不是一个或多个空格字符)

代码

以下任一方法都有效。

See the first regex in use here

See the second regex in use here

\s+A\s+\/Modules(?:\/[^\/]+){2}\/(?:branches|trunk|tags)$
\s+A\s+\/Modules\/[^\/]+\/[^\/]+\/(?:branches|trunk|tags)$

答案 1 :(得分:0)

  • 我假设你有类似这样的代码

    my $str = 'A /Modules/framework/odd-core/tags';
    
    if ( $str =~ /\s+A\s+\/Modules\/\w\/\w\/branches|trunk|tags$/ ) { ... }
    
  • 首先,如果您正在编写与斜杠/匹配的模式,那么更改为不同的分隔符会更加简单。我们可以使用!之类的任何非空格字符,只要前面有m

    if ( $str =~ m!\s+A\s+/Modules/\w/\w/branches|trunk|tags$! ) { ... }
    
  • 现在,字符串A之前没有空格,因此初始\s+不匹配。我们将其删除

    if ( $str =~ m!A\s+/Modules/\w/\w/branches|trunk|tags$! ) { ... }
    
  • 现在,您尝试将frameworkodd-core\w匹配,后者仅匹配单个字母数字字符或下划线。让我们添加一个连字符-来制作一个新的字符类[\w-],并附加一个+来匹配"一个或多个"

    if ( $str =~ m!A\s+/Modules/[\w-]+/[\w-]+/branches|trunk|tags$! ) { ... }
    
  • 现在您正在匹配A\s+/Modules/framework/odd-core trunk < / strong> tags$。让我们放入非捕获括号,让它说出我认为你的意思

    if ( $str =~ m!A\s+/Modules/[\w-]+/[\w-]+/(?:branches|trunk|tags)$! ) { ... }
    

    这应该有效!

更新

由于您的问题已更新,以显示A之前确实存在空格,您可以添加回\s+,但我认为没有它的模式可能会很好