我不确定我是否把问题回答对了。
我想用一个正则表达式来满足这两个文本。
text1 = 'foobar';
text2 = 'foobar-baz';
text1的预期输出
$1
应为bar
$2
应为''
text2的预期输出
$1
应为bar
$2
应为baz
以下是我尝试过的:
/foo([a-z0-9-_=+/]+)(-(.*))?/i
text1
的结果是正确的,但对于text2
,$1
得到完整的字符串foobar-baz
此处的问题是由于第一个捕获组中可能包含-
。有两种情况:
-
字符串中有一个或多个
-
,您希望选择最后一个由连字符分隔的组。直觉上,我们想到贪婪的量词,以及一个简单的解决方案,比如:input.match(/foo([a-z0-9_=+/-]+)-(.*)/)
会起作用。
-
然而,第二种情况,字符串中没有
-
,再加上前一种情况,会导致问题。由于
[a-z0-9_=+/-]+
包含-
,如果将-(.*)
设为可选,则在第一种情况下给定输入,它将刚好匹配字符串的末尾,并将所有内容放入第一个捕获组中。
我们需要控制回溯行为,以便当至少有一个-
时,它必须匹配它并匹配最后一个,并允许第一组在没有-
时狼吞虎咽。
一个对当前正则表达式进行最小更改的解决方案是:
input.match(/foo([a-z0-9_=+/-]+?)(?:-([a-z0-9_=+/]*))?$/)
懒惰量词使引擎首先从最左边的-
开始尝试,锚$
和末尾没有-
的字符类迫使引擎仅在最后一个-
(如果有的话)进行拆分。
注意,当不存在-
时,第二捕获组将是undefined
。
样本输入输出:
'foogoobarbaz'.match(/foo([a-z0-9_=+/-]+?)(?:-([a-z0-9_=+/]*))?$/)
> [ "foogoobarbaz", "goobarbaz", undefined ]
'foogoobar-baz'.match(/foo([a-z0-9_=+/-]+?)(?:-([a-z0-9_=+/]*))?$/)
> [ "foogoobar-baz", "goobar", "baz" ]
'foogoo-bar-baz'.match(/foo([a-z0-9_=+/-]+?)(?:-([a-z0-9_=+/]*))?$/)
> [ "foogoo-bar-baz", "goo-bar", "baz" ]
您可以使用非捕获组:
/foo([a-z0-9-_=+/]+)(?:-(.*))?/i
这解决了避免附加捕获组的问题。但是,您的模式仍然存在将-
作为第一个字符串的有效字符的问题。正因为如此,当您针对"foobar-baz"执行模式时,整个片段"barbaz"将匹配模式中的第一组。
你必须决定你想要匹配的是什么;你的规则目前与你寻求的结果不一致。如果从第一组中删除-
:
/foo([a-z0-9_=+/]+)(?:-(.*))?/i
然后你就会得到你说要找的结果。