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

Sup*_*iyi 6 regex pcre

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

/abc/foo/bar(/*) 
Run Code Online (Sandbox Code Playgroud)

要么

/abc/foo/bar/stop
Run Code Online (Sandbox Code Playgroud)

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

如果我只是这样做:

^(/.*[^/])/*$
Run Code Online (Sandbox Code Playgroud)

包括所有斜线在内的哪个是贪婪的,直到我去除可能的最后一次出现; 但是为了接受我有一个可选的"/ 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
Run Code Online (Sandbox Code Playgroud)

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

/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)
Run Code Online (Sandbox Code Playgroud)

如果这一点足够清楚,请告诉我.谢谢!

eli*_*ide 4

尝试这个:

/^(?:\/+(?!$|(?:stop\/?))[^\/]+)*/
Run Code Online (Sandbox Code Playgroud)

Regex101 演示

解释:

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

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

正则表达式可视化

这是带有工作单元测试的Debuggex 演示

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

/^.+?(?=\/*$|\/+stop\b)/
Run Code Online (Sandbox Code Playgroud)

这以非贪婪的方式匹配一个或多个字符,然后当匹配后的内容是以下之一时停止:

  1. 字符串末尾 ( $),前面可能有一个或多个斜杠 ( \/*)
  2. 一个或多个斜杠、单词停止和单词中断。

这是此选项的Regex101 演示。

编辑 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 

*/
Run Code Online (Sandbox Code Playgroud)