在javascript中满足二合一正则表达式模式



我不确定我是否把问题回答对了。

我想用一个正则表达式来满足这两个文本。

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

然后你就会得到你说要找的结果。

最新更新