115

I'm new to Regex and I'm trying to work it into one of my new projects to see if I can learn it and add it to my repitoire of skills. However, I'm hitting a roadblock here.

I'm trying to see if the user's input has illegal characters in it by using the .search function as so:

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

However, when I try to execute the function this line is contained it, it throws the following error for that specific line:

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

]/: Nothing to repeat

I can't for the life of me see what's wrong with my code. Can anyone point me in the right direction?

Liam
  • 27,717
  • 28
  • 128
  • 190
esqew
  • 42,425
  • 27
  • 92
  • 132
  • My code was just throwing `SyntaxError: nothing to repeat` with no indication of what the problem was. This question made me realize it was regex-related and I had just added a `'*'` regex and it all made sense now. – Akaisteph7 Feb 16 '23 at 17:55

7 Answers7

151

You need to double the backslashes used to escape the regular expression special characters. However, as @Bohemian points out, most of those backslashes aren't needed. Unfortunately, his answer suffers from the same problem as yours. What you actually want is:

The backslash is being interpreted by the code that reads the string, rather than passed to the regular expression parser. You want:

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

Note the quadrupled backslash. That is definitely needed. The string passed to the regular expression compiler is then identical to @Bohemian's string, and works correctly.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
andrewdski
  • 5,255
  • 2
  • 20
  • 20
  • 4
    btw, the quadruple \ is only needed in some langs; eg java yes, perl not – Bohemian Jun 09 '11 at 22:13
  • A likewise-encountered duh moment that I ran into as well. Good to be reminded that backslash gets interpreted by the language syntax first, then by the RegExp. – enorl76 Jul 30 '18 at 19:51
  • I just want to mention that some explanation for javascript str.search method seems as string between quotes is pure string e.g. str.search("hello") so somebody may think that if desire string is just e.g. asterisk, the correct syntax would be str.search("*") which lead to the same error "Nothing to repeat". Correct is str.search("\\*") – portal TheAnGeLs Jul 29 '21 at 12:54
9

Building off of @Bohemian, I think the easiest approach would be to just use a regex literal, e.g.:

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

Regex literals are nice because you don't have to escape the escape character, and some IDE's will highlight invalid regex (very helpful for me as I constantly screw them up).

NobodyMan
  • 2,381
  • 4
  • 29
  • 35
8

For Google travelers: this stupidly unhelpful error message is also presented when you make a typo and double up the + regex operator:

Okay:

\w+

Not okay:

\w++
Tomáš Hübelbauer
  • 9,179
  • 14
  • 63
  • 125
4

This can also happen if you begin a regex with ?.

? may function as a quantifier -- so ? may expect something else to come before it, thus the "nothing to repeat" error. Nothing preceded it in the regex string so it didn't get to quantify anything; there was nothing to repeat / nothing to quantify.

? also has another role -- if the ? is preceded by ( it may indicate the beginning of a lookaround assertion or some other special construct. See example below.

If one forgets to write the () parentheses around the following lookbehind assertion ?<=x, this will cause the OP's error:

Incorrect: const xThenFive = /?<=x5/;

Correct: const xThenFive = /(?<=x)5/;

This /(?<=x)5/ is a positive lookbehind: we're looking for a 5 that is preceded by an x e.g. it would match the 5 in x563 but not the 5 in x652.

David
  • 895
  • 8
  • 12
3

Well, in my case I had to test a Phone Number with the help of regex, and I was getting the same error,

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

So, what was the error in my case was that + operator after the / in the start of the regex. So enclosing the + operator with square brackets [+], and again sending the request, worked like a charm.

Following will work:

/[+]923[0-9]{2}-(?!1234567)(?!1111111)(?!7654321)[0-9]{7}/

This answer may be helpful for those, who got the same type of error, but their chances of getting the error from this point of view, as mine! Cheers :)

2

Firstly, in a character class [...] most characters don't need escaping - they are just literals.

So, your regex should be:

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

This compiles for me.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • @Icet do the other answers not work for you? If not, what input is "not working"? – Bohemian Jun 26 '17 at 08:38
  • For example +44 as an input is not working. This solution works fine str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); – Icet Jun 26 '17 at 10:07
2

for example I faced this in express node.js when trying to create route for paths not starting with /internal

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

and after long trying it just worked when passing it as a RegExp Object using new RegExp()

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

this may help if you are getting this common issue in routing

Abraham
  • 12,140
  • 4
  • 56
  • 92