【问题标题】:Why does String.match( / \d*/ ) return an empty string?为什么 String.match( / \d*/ ) 返回一个空字符串?
【发布时间】:2019-03-12 11:29:46
【问题描述】:

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

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

【问题讨论】:

  • * 字符匹配zero 或连续出现多个字符,+ 字符相似但匹配一个或多个。
  • 从左到右检查字符串是否匹配。由于\d* 可以在索引 0 处匹配一个空字符串,因此它会在该处返回一个匹配项。

标签: javascript regex


【解决方案1】:

/\d*/

表示“匹配从字符串开头开始的 0 个或多个数字”。

当你开始你的字符串的开头时,它会立即碰到一个非数字并且不能再继续了。然而,这被认为是成功的匹配,因为“0 或更多”。

您可以通过

尝试“1 个或多个”
/\d+/

或者你可以告诉它匹配字符串末尾的“0个或更多”:

/\d*$/

在 Python 中查找所有内容

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

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

.match() 在 JavaScript 中,仅返回第一个匹配项,即上述数组中的第一个元素。

【讨论】:

  • 啊,区分字符串的开头和结尾有助于澄清一点。所以问题是搜索从字符串的开头开始,并且每个字符串都以空字符串“”开头,这将导致零位或多位数字的匹配成功。如果我的理解不正确,请告诉我。谢谢你的解释,马丁。
  • 就是这样。您从头开始,然后点击了一个非数字,因此 0 个数字被“成功”匹配。
  • 更新了 Python 中的示例,可能会进一步阐明。
【解决方案2】:

请记住,match 正在寻找它可以找到的与给定正则表达式匹配的第一个子字符串。

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

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

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

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

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

【讨论】:

  • 这就是 PCRE 所做的,但不是 POSIX 正则表达式。 POSIX 总是找到最长的匹配项。
  • @VadimPushtaev:我对正则表达式的所有风格都不是很熟悉,但这就是 Javascript 的作用。
  • 谢谢你,@StriplingWarrior。我认为我感到困惑的是字符串(尽管已填充)以空字符串开头。我没有想到字符串“one to 100”包含字符串“”。但是由于正则表达式无法在第一个字符处找到数字,因此它返回了空字符串“”,它仍然符合匹配条件,因为“”等于零个或多个数字。但是,如果这符合匹配条件,那么正则表达式引擎是否甚至会费心查看第一个字符,如果是,为什么?
  • @capolo2:是的,因为正如您从我的答案中的代码示例中看到的那样,它必须知道它是否可以通过添加来匹配更大的字符串(仍然从同一个地方开始)输入开头的空字符串。
  • @VadimPushtaev:不,POSIX 正则表达式会返回相同的结果(除非您必须使用[0-9][[:digit:]] 而不是\d)。仅当正则表达式采用交替时,不同长度的匹配才会成为问题。 (ref)
【解决方案3】:

正如@StriplingWarrior 下面所说,空字符串是第一个匹配项,因此它被返回。我想补充一点,您可以通过注意函数match 返回的“索引”字段来判断正则表达式匹配的内容。例如,这是我在 Chrome 中运行您的代码时得到的:

["", index: 0, input: "one to 100"]

【讨论】:

  • 谢谢@Rafid。我将不得不多读一点。我想我不明白为什么它匹配空字符串,当字符串内部有匹配时。另外,关于索引,为什么'0'对应的是空字符串,而不是字符串中的第一个元素('o')?
【解决方案4】:

* 表示 0 或更多,因此匹配 0 次。您需要使用+ 1 个或更多。默认是贪心的,所以会匹配100:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-22
    • 2021-10-09
    • 2013-04-09
    相关资源
    最近更新 更多