正则表达式在一个可选字符串上匹配非贪婪,在另一个字符串上贪婪

时间:2014-07-11 17:53:45

标签: regex pcre

我已经研究了一段时间,并且没有找到匹配以下模式的线索(虽然我也是正则表达式的新手),它看起来像

/abc/foo/bar(/*) 

/abc/foo/bar/stop

所以我想匹配并捕获上面的字符串为/ abc / foo / bar。现在" /停止"是一个可选的字符串,可以附加在模式的末尾。目标是获得所需的捕获,同时忽略"停止"如果它们出现(如果"停止"多次停留在第一个"停止"),同时允许尽可能多的斜线在中间除了线末端的斜线。

如果我只是这样做:

^(/.*[^/])/*$

在我删除可能的最后一次出现之前,包含所有斜杠是贪婪的;但是为了接受我有一个可选的" / stop"的第二种情况,我需要以非贪婪的方式进行匹配,直到找到第一种可能的" / stop"并停在那里。

我如何制作一个匹配两种情况的正则表达式?

编辑:不确定我之前的例子是否不够清楚。尝试提供更多,说我想匹配并捕获" / abc / foo / bar"在以下所有字符串中:

/abc/foo/bar
/abc/foo/bar/
/abc/foo/bar///
/abc/foo/bar/stop
/abc/foo/bar/stop/foo/bar/stop/stop
/abc/foo/bar//stop

虽然它不符合以下任何一项:

/abc/foo/bar/sto (will match the whole "/abc/foo/bar/sto" instead)
/abc/foo/bar/abc/foo/bar (it will catch "/abc/foo/bar/abc/foo/bar" instead)

让我知道这是否足够清楚。谢谢!

2 个答案:

答案 0 :(得分:3)

试试这个:

/^(?:\/+(?!$|(?:stop\/?))[^\/]+)*/

Regex101 Demo

说明:

这匹配字符串的开头(^),后跟以下模式的零个或多个实例:

  • 一个或多个斜杠(\/+)未跟随字符串末尾($)或stop,后跟
  • 一个或多个非斜杠字符([^\/]+

Regular expression visualization

这是一个Debuggex Demo工作单元测试。

编辑:这是一个替代方案,可以说更简单,正则表达式:

/^.+?(?=\/*$|\/+stop\b)/

这会以非贪婪的方式匹配一个或多个字符,然后在匹配后的任何内容为以下之一时停止:

  1. 字符串的结尾($),可能前面有一个或多个斜杠(\/*
  2. 一个或多个斜杠,单词停止和单词分隔符。
  3. 此处有Regex101 demo此选项。

    编辑2:如果您想对此进行测试,这是一个简单的JavaScript测试,它针对各种测试字符串测试上面的第二个正则表达式,并将结果记录到控制台:

    var re = /^.+?(?=\/*$|\/+stop\b)/,
        test_strings = ["/abc/foo/bar",
                        "/abc/foo/bar/",
                        "/abc/foo/bar///",
                        "/abc/foo/bar/stop",
                        "/abc/foo/bar/stop/foo/bar/stop/stop",
                        "/abc/foo/bar//stop",
                        "/abc/foo/bar/sto",
                        "/abc/foo/bar/abc/foo/bar"];
    for(var s = 0; s < test_strings.length; s++) {
        console.log(test_strings[s].match(re)[0]);
    }
    
    /*
    Results:
    
    /abc/foo/bar
    /abc/foo/bar
    /abc/foo/bar
    /abc/foo/bar
    /abc/foo/bar
    /abc/foo/bar
    /abc/foo/bar/sto
    /abc/foo/bar/abc/foo/bar 
    
    */
    

答案 1 :(得分:2)

您可以尝试这样的事情:

^((?:/[^/]+)+?)(?:/+|/+stop(?:/.*)?)$

demo

如果原子组可用,最好写一下:

^((?:/[^/]+)+?)(?>/+$|/+stop(?:/.*)?)

demo

如果可以预见:

^/(?>[^/]+|/(?!/*(?:$|stop(?:/|$))))+

demo

ps:如果您的分隔符是斜杠,请不要忘记逃避斜杠。

正如Ed Cottrell所注意到的那样,原子分组等功能在Javascript等语言或Python的re模块中不可用。但是,使用前瞻是自然原子这一事实可以有效地模拟该特征:(?>a+)&lt; =&gt; (?=(a+))\1