Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does *.* in regex return undefined

At least, in Javascript, tested on both Chrome and Node.js:

new RegExp(/foo(optional)*boo/).exec('foooptionalboo')

Will match the optional in parentheses:

[ 'foooptionalboo',
'optional',
index: 0,
input: 'foooptionalboo' ]

But if you want there to be something in between the optional:

new RegExp(/foo.*(optional)*.*boo/).exec('foooptionalboo')

Then the optional is not found:

[ 'foooptionalboo',
'optional',
index: 0,
input: 'foooptionalboo' ]

Why is this?

like image 837
A. Duff Avatar asked Apr 15 '26 02:04

A. Duff


2 Answers

The .* matches optional before (optional)* has a chance to.

Make it non-greedy (with a ?) so it won't match if the thing following it will.

/foo.*?(optional)*.*boo/.exec("foooptionalboo")
like image 131
Quentin Avatar answered Apr 17 '26 15:04

Quentin


The problem with Quentin's answer is that .*? followed with an optional greedy subpattern (optional)? and a greedy dot matching pattern .* works in such a way that the .*? only matches the empty string, and .* takes up the whole rest of the string.

Why does it happen? Because lazy subpatterns that can match an empty string (and it will always match here since it can match an empty string) work so: once the lazy subpattern matches, other subpatterns to the right are tried, and if a match is found, the lazy subpattern is not re-tried. enter image description here

To really grab an optional part, either use a specific pattern where no .* appears after the optional part, or (to make it more generic) use a tempered greedy token:

foo(?:(?!optional).)*(optional)*.*boo
   ^^^^^^^^^^^^^^^^^^

See the regex demo

The (?:(?!optional).)* is the tempered greedy token that matches any text up to the first optional substring.

like image 37
Wiktor Stribiżew Avatar answered Apr 17 '26 15:04

Wiktor Stribiżew



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!