我是正则表达式领域的新手 我在下面发布的所有内容都是我代码中的简化示例。
我有一个字符串,假设test_1,some_2,foo,bar_4,
我想用title: test (1) title: some (2) title: foo () title: bar (4)
替换
我现在拥有的是(有效):
var test = "test_1,some_2,foo,bar_4,";
console.log(test.replace(/(.*?)(?:_(\d))?,/g, "title: $1 ($2)\n"));
输出:
title: test (1)
title: some (2)
title: foo ()
title: bar (4)
为了使事情正确,我想在最后一项之后摆脱昏迷。该列表看起来像test_1,some_2,foo,bar_4
(bar_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: ()
我的问题是:为什么?怎么解决?实际的正则表达式是否有任何可能的改进?
答案 0 :(得分:4)
您正在获得最后一次误判匹配,因为您的正则表达式匹配空字符串:
"".replace(/(.*?)(?:_(\d))?(?:,|$)/g, "title: '$1' ('$2') ");
title: '' ('')
因此,在所有字符消耗完之后,它将匹配一个空字符串。
您可以通过将第一个组更改为非可选项进行控制,因为它显示的不是真正的可选组。
/(.*?)(?:_(\d))?(?:,|$)/g
--^^--
例如,
var str = "test_1,some_2,foo,bar_4";
test.replace(/([a-z]+)(?:_(\d))?(?:,|$)/gi, "title: '$1' ('$2') ");
title: test (1) title: some (2) title: foo () title: bar (4)
即,
([a-z]+)
:匹配至少一个字母字符,gi
:使字符串不区分大小写。答案 1 :(得分:1)
作为最简单的解决方案,您可以在匹配正则表达式之前将尾随逗号添加到原始字符串。
答案 2 :(得分:1)
你的问题是你的模式不仅匹配你想要的,还匹配空字符串:
(.*?) # 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", ""]
您至少有两种方法可以解决问题:
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) "