在JavaScript中使用正则表达式时,"Nothing to repeat"错误是什么意思?

115

我是正则表达式的新手,并尝试将其应用于我的新项目中,以查看是否可以学习并将其添加到我的技能库中。但是,我在这里遇到了障碍。

我正在尝试使用.search函数来查看用户输入中是否存在非法字符:

if (name.search("[\[\]\?\*\+\|\{\}\\\(\)\@\.\n\r]") != -1) {
    ...
}

然而,当我尝试执行包含此行的函数时,它会针对该特定行抛出以下错误:

Uncaught SyntaxError: Invalid regular expression: /[[]?*+|{}\()@.

]/: Nothing to repeat

我死活看不出我的代码哪里出了问题。有没有人能指点我一下?


我的代码一直抛出 SyntaxError: nothing to repeat 的错误,但没有任何指示问题所在。这个问题让我意识到它与正则表达式有关,我刚刚添加了一个 '*' 正则表达式,现在一切都清晰了。 - Akaisteph7
7个回答

152

需要将用于转义正则表达式特殊字符的反斜杠加倍。但是,正如@Bohemian指出的那样,大多数这些反斜杠是不需要的。不幸的是,他的答案和你的一样存在问题。实际上您需要的是:

反斜杠被解释为读取字符串的代码而不是传递给正则表达式解析器。您需要使用:

"[\\[\\]?*+|{}\\\\()@.\n\r]"

注意四个反斜杠。这绝对是必需的。然后传递给正则表达式编译器的字符串与@Bohemian的字符串完全相同,并且可以正确工作。


4
顺便说一下,在某些语言中只需要四个反斜杠;例如 Java 中是这样的,而 Perl 则不需要。 - Bohemian
我也遇到了类似的“傻瓜”时刻。提醒我们反斜杠首先被语言语法解释,然后才是 RegExp。 - enorl76
我想提一下,关于JavaScript str.search方法的一些解释似乎是在引号之间的纯字符串,例如str.search("hello"),因此有人可能会认为,如果期望的字符串只是星号,正确的语法应该是str.search(""),这将导致相同的错误“Nothing to repeat”。正确的写法是str.search("\")。 - portal TheAnGeLs

9

在@Bohemian的基础上,我认为最简单的方法是只使用正则表达式字面量,例如:

if (name.search(/[\[\]?*+|{}\\()@.\n\r]/) != -1) {
    // ... stuff ...
}

正则表达式字面量很不错,因为你不需要转义转义字符,而一些IDE会突出显示无效的正则表达式(对我来说非常有帮助,因为我经常搞砸它们)。


8
对于谷歌旅行者:当您在使用+正则表达式操作符时犯了错并出现重复,此愚蠢且无用的错误信息也会被呈现出来。
好的:
\w+

不可行:

\w++

4
任何由 +* 符号组合而成的字符实际上都是有效的。 - Sharcoux
1
你救了我的代码。我有个错别字/ (* \ s *) /。是的,这个错误提示非常不友好。 - Tomáš Wróbel
@Sharcoux - 是的!我本来想用 * 替换 +,但最终两个都用上了。谢谢! - Katie Byers

4
这也可能发生在使用以?开始的正则表达式时。 ?可以作为量词符,因此?可能希望在它之前出现其他内容,因此会出现“没有重复内容”的错误。在正则表达式字符串中,它之前没有任何内容,因此它无法量化任何东西;没有任何内容可重复/量化。 ?还有另一个作用——如果在?之前有(,它可能表示环视断言或其他特殊结构的开始。请参见下面的示例。
如果忘记在以下顺序断言?<=x周围写()括号,则会导致OP的错误:
不正确的写法:const xThenFive = /?<=x5/; 正确的翻译如下:

正确写法: const xThenFive = /(?<=x)5/;

/(?<=x)5/ 是一个正向后顾引用:我们要找的是一个紧随着 x 之后出现的 5,例如它会匹配 x563 中的 5,但不会匹配 x652 中的 5


4

在我的情况下,我需要使用正则表达式测试电话号码,但是我一直遇到相同的错误。

Invalid regular expression: /+923[0-9]{2}-(?!1234567)(?!1111111)(?!7654321)[0-9]{7}/: Nothing to repeat'

因此,在我的情况下,正则表达式开头的/之后的+运算符是错误的。因此,将+运算符用方括号[+]括起来,然后再次发送请求,就能成功运行。
以下内容可用:
/[+]923[0-9]{2}-(?!1234567)(?!1111111)(?!7654321)[0-9]{7}/

这个答案可能对那些遇到相同错误类型的人有所帮助,但他们从这个角度获得错误的机会与我相同!干杯 :)

1
你为什么不直接转义加号而是要将它整个移动呢?(\+) - esqew
谢谢让我理解@esqew的另一个方法,但是我找到了另一个解决方案 :) - Aneeq Ahmad

2

首先,在字符类[...]中,大多数字符不需要转义 - 它们只是字面量。

因此,你的正则表达式应该是:

"[\[\]?*+|{}\\()@.\n\r]"

这对我来说是可以编译的。


@Icet,其他答案对您无效吗?如果是,哪些输入是“无效的”? - Bohemian
例如,输入+44无法正常工作。这个解决方案很好地使用了str.replace(/[-[]/{}()*+?.\^$|]/g, "\$&"); - Icet

2
例如,我在使用Express Node.js创建路径路由时遇到了这个问题,这些路径不是以/internal开头。
app.get(`\/(?!internal).*`, (req, res)=>{

经过多次尝试,只有将其作为RegExp对象传递并使用new RegExp()时才能使其正常工作。

app.get(new RegExp("\/(?!internal).*"), (req, res)=>{

这可能有助于你解决路由中的常见问题。

太好了!由于某些原因,new RegExp成功解决问题了!谢谢 - Uriel Alves

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