【问题标题】:Match text followed by optional pattern匹配文本后跟可选模式
【发布时间】:2014-08-29 09:40:08
【问题描述】:

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

这是我要匹配match/string的三个输入字符串的示例

/any/path/match/string
/any/path/match/string/pattern
/any/path/match/string/pattern/something/else

其中/any/path/pattern 是静态文本,match/string 可以是任何文本。

我试过了

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

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

【问题讨论】:

  • (?=...)? 这样的语法是无操作的。好吧...“后跟可选模式”没有多大意义。你想做什么?请举出具体例子。
  • 基本上我正在尝试匹配“/any/path”和“/pattern”之间的文本,其中“/pattern”可能存在或不存在于输入字符串中。
  • 问题在于,由于match/string 可能是“任何文本”,那么其中一个可能是/match/string/pattern/something/else。如果你正确定义了你想要做什么,那么代码会更加明显

标签: regex perl


【解决方案1】:

正如您已经推测的那样,您的问题是贪婪匹配。

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

print +(split m{/pattern\b}, $1)[0] if m{^/any/path/(.+)};

不过,要使用单个正则表达式来做到这一点,有两种方法:

  1. 限制任何字符 . 可以匹配的内容,方法是在其前面放置一个否定的前瞻断言。
  2. 对结束边界条件使用非贪婪匹配。

下面演示了这两种方法:

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

输出:

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

【讨论】:

  • print +(split m{/pattern\b}, $1)[0] if m{^/any/path/(.+)}?我不知道那是做什么的!
【解决方案2】:

你可以使用这个正则表达式:

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

Working demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多