Search code examples
javascriptc++regexstdecmascript-2016

How to match only those numbers which have an even number of `%`s preceding them?


I want to catch numbers appearing anywhere in a string, and replace them with "(.+)".

But I want to catch only those numbers which have an even number of %s preceding them. No worries if any surrounding chars get caught up: we can use capture groups to filter out the numbers.

I'm unable to come up with an ECMAscript regular expression.

Here is the playground:

abcd %1 %%2 %%%3 %%%%4 efgh

abcd%12%%34%%%666%%%%11efgh

A successful catch will behave like this:
desired behaviour


Things I have tried:

attempt 1

attempt 2

attempt 3


If you have realised, the third attempt is almost working. The only problems are in the second line of playground. Actually, what I wanted to say in that expression is:

Match a number if it is preceded by an even number of %s AND either of the following is true:

  • The above whole expression is preceded by nothing [absence of (unconsumed or otherwise) character].
  • The above whole expression is preceded by a character other than %.

Is there a way to match the absence of a character?
That's what I was trying to do by using \0 in the third attempt.


Solution

  • You can use (?:[^%\d]|^|\b(?=%))(?:%%)*(\d+) as a pattern, where your number is stored into the first capturing group. This also treats numbers preceded by zero %-characters.

    This will match the even number of %-signs, if they are preceded by:

    • neither % nor number (so we don't need to catch the last number before a %, as this wouldn't work with chains like %%1%%2)
    • the start of the string
    • a word boundary (thus any word character), for the chains mentioned above

    You can see it in action here