Javascript 正则表达式匹配额外的空组
我是正则表达式领域的新手。Javascript 正则表达式匹配额外的空组,javascript,regex,Javascript,Regex,我是正则表达式领域的新手。 下面我将发布的只是我代码中的简化示例 我有一个字符串,比如说test\u 1,some\u 2,foo,bar\u 4,,我想用title:test(1)title:some(2)title:foo()title:bar(4) 我现在拥有的是(有效的): 哪些产出: title: test (1) title: some (2) title: foo () title: bar (4) 为了使事情恢复正常,我想在做完最后一件事后摆脱昏迷状态。列表将类似于测试1、部分
下面我将发布的只是我代码中的简化示例 我有一个字符串,比如说
test\u 1,some\u 2,foo,bar\u 4,
,我想用title:test(1)title:some(2)title:foo()title:bar(4)
我现在拥有的是(有效的):
哪些产出:
title: test (1)
title: some (2)
title: foo ()
title: bar (4)
为了使事情恢复正常,我想在做完最后一件事后摆脱昏迷状态。列表将类似于测试1、部分测试2、foo、bar\u 4
(bar\u 4后无昏迷)
因此,新代码:
var test = "test_1,some_2,foo,bar_4";
console.log(test.replace(/(.*?)(?:_(\d))?(?:,|$)/g, "title: $1 ($2) "));
出了点问题。结尾还有一个额外的空匹配:
title: test (1)
title: some (2)
title: foo ()
title: bar (4)
title: ()
我的问题是:为什么?如何修复它?实际正则表达式是否有任何可能的改进
最简单的解决方案是,在匹配正则表达式之前,只需在原始字符串中添加尾随逗号即可。因为正则表达式匹配的是空字符串,所以得到的是最后一个假阳性匹配:
"".replace(/(.*?)(?:_(\d))?(?:,|$)/g, "title: '$1' ('$2') ");
(.*?) # matches any string (including an empty one) not containing \n
(?:_(\d))? # it is an optional group
(?:,|$) # it matches a comma or the end of the string
因此,在您的情况下,在使用完所有字符后,它将匹配一个空字符串
您可以通过将第一个组更改为非可选组来进行控制,因为它并不是如图所示的可选组
/(.*?)(?:_(\d))?(?:,|$)/g
--^^--
比如说,
var str = "test_1,some_2,foo,bar_4";
test.replace(/([a-z]+)(?:_(\d))?(?:,|$)/gi, "title: '$1' ('$2') ");
就是
:至少匹配一个字母字符,以及([a-z]+)
:使字符串不区分大小写gi
"".replace(/(.*?)(?:_(\d))?(?:,|$)/g, "title: '$1' ('$2') ");
(.*?) # matches any string (including an empty one) not containing \n
(?:_(\d))? # it is an optional group
(?:,|$) # it matches a comma or the end of the string
因此,当正则表达式引擎根据模式计算字符串结尾时,它会看到:
- 第一个组匹配,因为正在处理空字符串
- 第二组匹配,因为它是可选的
- 第三组匹配,因为正在处理字符串的结尾
match
方法,您可以在控制台中清楚地看到它
> s.match(/(.*?)(?:_(\d))?(?:,|$)/g)
["test_1,", "some_2,", "foo,", "bar_4", ""]
处理此问题时,您至少有两种选择:
- 以与空字符串不匹配但仍符合您需要的方式更改模式的第一组(这取决于您必须处理的字符串)
- 保持regex不变,并处理
返回的字符串以删除不需要的部分replace
> var result = s.replace(/(.*?)(?:_(\d))?(?:,|$)/g, "title: $1 ($2) ");
> result = result.slice(0, result.lastIndexOf("title"));
"title: test (1) title: some (2) title: foo () title: bar (4) "
有一个空匹配,因为正则表达式的所有部分都是可选的:
*?
可以匹配0个字符,(?:…)?
是可选组,在上次更改时,您将逗号设置为可选。更改为:/(.+?)(?:(\d))(?:,|$)/
谢谢您的精彩回答。我认为“.*”不能匹配空字符串。这很微妙。现在一切都清楚了;)谢谢你的回答!亚历山大的回答首先帮助了我,但非常感谢你的解释+1.
> var result = s.replace(/(.*?)(?:_(\d))?(?:,|$)/g, "title: $1 ($2) ");
> result = result.slice(0, result.lastIndexOf("title"));
"title: test (1) title: some (2) title: foo () title: bar (4) "