为什么String.match(/ \d*/)返回一个空字符串?

6

有人能帮我理解为什么使用\d*返回一个包含空字符串的数组,而使用\d+却返回["100"](如预期)。我知道为什么\d+有效,但不明白为什么\d*无效。使用*是否导致它返回零长度的匹配项?这是如何工作的呢?

var str = 'one to 100';
var regex = /\d*/;
console.log(str.match(regex));
// [""]

2
星号(*)匹配零个或多个相同字符,加号(+)类似但是至少匹配一个。 - GillesC
1
字符串从左到右进行匹配检查。由于\d*可以在索引0处匹配一个空字符串,因此它会在那里返回一个匹配。 - nhahtdh
4个回答

10

记住,match是在查找第一个与给定正则表达式匹配的子字符串。

*表示可能有零个或多个某物,因此\d*表示您正在查找包含零个或多个数字的字符串。

如果您的输入字符串以数字开头,则整个数字将匹配。

"5 to 100".match(/\d*/); // "5"
"5 to 100".match(/\d+/); // "5"

但是由于第一个字符不是数字,match() 函数认为字符串的开头(没有字符)与正则表达式相匹配。

由于您的字符串不以任何数字开头,因此空字符串是与该正则表达式匹配的输入的第一个子字符串。


1
这就是PCRE所做的,但不是POSIX正则表达式。 POSIX总是找到最长的匹配。 - Vadim Pushtaev
1
@VadimPushtaev:我对所有正则表达式的变种并不非常熟悉,但这是Javascript的处理方式。 - StriplingWarrior
谢谢@StriplingWarrior。我觉得我不明白的是字符串(虽然已经被填充)以空字符串开头。我没有考虑字符串“one to 100”包含字符串“”。但是由于正则表达式无法在第一个字符找到数字,因此它返回了空字符串“”,这仍然符合匹配条件,因为“”等于零个或多个数字。但是如果这也符合匹配条件,那么正则表达式引擎还会查看第一个字符吗?如果是,为什么呢? - tbutman
@capolo2:是的,因为从我回答中的代码示例中可以看出,它必须知道是否可以通过在输入开头添加空字符串来匹配更大的字符串(仍然从同一位置开始)。 - StriplingWarrior
3
@VadimPushtaev:不,POSIX正则表达式将返回相同的结果(除非您必须使用[0-9][[:digit:]]代替\d)。只有当正则表达式使用交替时,不同长度的匹配才会成为问题。 (参考 - Alan Moore

4

/\d*/

的意思是“从字符串开头开始匹配0个或多个数字”。当您从字符串开头开始匹配时,它立即遇到一个非数字字符,无法继续匹配。但是这仍然被认为是一个成功的匹配,因为“0个或多个数字”。您可以尝试使用/\d+来进行“1个或多个”匹配。
/\d+/

或者你可以告诉它匹配字符串结尾处的“0或更多”:
/\d*$/

在Python中使用findall方法

在Python中,有一个findall()方法,它返回与正则表达式匹配的字符串的所有部分。

re.findall(r'\d*', 'one to 100')
# => ['', '', '', '', '', '', '', '100', '']

.match()是JavaScript中的一个函数,它只返回第一个匹配项,也就是上述数组中的第一个元素。


啊,区分字符串的开头和结尾有助于澄清一些事情。所以问题在于搜索从字符串的开头开始,并且每个字符串都以空字符串""开头,这将导致零个或多个数字的匹配成功。如果我的理解有误,请告诉我。感谢你的解释,马丁。 - tbutman
就是这样。你从头开始,然后遇到了一个非数字字符,因此没有匹配到0个数字字符。 - Martin Konecny
更新了一个来自Python的例子,这可能会更加清晰明了。 - Martin Konecny
在JavaScript中有一个'matchAll'方法。 - undefined

2

*代表0次或多次匹配。如果要匹配1次或多次,需要使用+。默认情况下是贪婪模式,因此会匹配100

var str = 'one to 100';
var regex = /\d+/;
console.log(str.match(regex));
// ["100"]

1
正如@StriplingWarrior在下面所说的,空字符串是第一个匹配项,因此它被返回。我想补充一点的是,你可以通过注意函数match返回的'index'字段来判断正则表达式的匹配情况。例如,当我在Chrome中运行你的代码时,就会得到下面的结果:
["", index: 0, input: "one to 100"]

1
谢谢,@Rafid。我需要再多读一些资料。我猜我不懂为什么它会匹配空字符串,当字符串中有一个匹配项的时候。另外,关于索引,为什么'0'对应空字符串而不是字符串中的第一个元素('o')? - tbutman
@tbutman 我也在问自己同样的问题。你得到答案了吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接