Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 正则表达式匹配额外的空组_Javascript_Regex - Fatal编程技术网

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) "