Regex 匹配文本,后跟可选模式

Regex 匹配文本,后跟可选模式,regex,perl,Regex,Perl,我正在尝试编写一个正则表达式,它匹配一个后跟可选模式的字符串 下面是三个输入字符串的示例,我想在其中匹配match/string /any/path/match/string /any/path/match/string/pattern /any/path/match/string/pattern/something/else 其中,/any/path和/pattern是静态文本,匹配/string可以是任何文本 我试过这个 print $1 if m,/any/path/(.+)(?=/pa

我正在尝试编写一个正则表达式,它匹配一个后跟可选模式的字符串

下面是三个输入字符串的示例,我想在其中匹配
match/string

/any/path/match/string
/any/path/match/string/pattern
/any/path/match/string/pattern/something/else
其中,
/any/path
/pattern
是静态文本,
匹配/string
可以是任何文本

我试过这个

print $1 if m,/any/path/(.+)(?=/pattern/)?,

但是它匹配整个输入字符串,因为
+
是贪婪的。

您可以使用以下正则表达式:

/any/path/(\w+?/\w+)/pattern|/any/path/(\w+?/\w+)$


正如您所猜测的,您的问题是贪婪匹配

请记住,如果您在使用正则表达式时遇到问题,您可以将逻辑分解为以下步骤:

print +(split m{/pattern\b}, $1)[0] if m{^/any/path/(.+)};
不过,要使用单个正则表达式实现这一点,有两种方法:

  • 通过在任何字符
    之前放置一个否定的先行断言来限制该字符可以匹配的内容
  • 对结束边界条件使用非贪婪匹配
  • 下面演示了这两种方法:

    use strict;
    use warnings;
    
    while (<DATA>) {
        print "\nString = $_";
    
        if (m{^/any/path/( (?:(?!/pattern\b).)* )}x) {
            print "  Neg Lookahead        - $1\n"
        }
    
        if (m{^/any/path/(.*?)(?:/pattern\b|$)}x) {
            print "  Nongreedy with bound - $1\n"
        }
    }
    __DATA__
    /any/path/match/string
    /any/path/match/string/pattern
    /any/path/match/string/pattern/something/else
    

    (?=…)?
    这样的语法是不可行的。。。“后面跟着一个可选模式”没有多大意义。你想干什么?请给出具体的例子。基本上,我正在尝试匹配“/any/path”和“/pattern”之间的文本,其中“/pattern”可能存在于输入字符串中,也可能不存在于输入字符串中。问题是,既然
    match/string
    可以是“任意文本”,那么它可能是
    /match/string/pattern/something/els
    。如果您正确定义了要执行的操作,那么如果m{^/any/path/(.+)},那么代码将更加明显
    print+(拆分m{/pattern\b},$1)[0]?我不知道那有什么用!
    
    String = /any/path/match/string
      Neg Lookahead        - match/string
      Nongreedy with bound - match/string
    
    String = /any/path/match/string/pattern
      Neg Lookahead        - match/string
      Nongreedy with bound - match/string
    
    String = /any/path/match/string/pattern/something/else
      Neg Lookahead        - match/string
      Nongreedy with bound - match/string