Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript .match regular expression with reverse quantifier (or parse right to left)

Given a string like such...

"ABCDEFG"

Is it possible to have a quantifier that works in "reverse" so to say?

For instance:

var foo = "ABCDEFG";
foo.match(/.{1,3}/g);

Results in:

// Array(3) ["ABC", "DEF", "G"]

What I'm trying achieve:

// Array(3) ["A", "BCD", "EFG"]

So regardless of the string length, the array is always a representation of the string, with each node 3 characters in length (except possibly the 1st) but always starting at the end of the string. So the first array item might be 1, 2 or 3 characters long, simply depending on what's "left over".

I have tried using the following to error:

foo.match(/.{-1,3}/g); // null
foo.match(/.{1,-3}/g); // null

Thinking perhaps I could use negatives similar to splitting strings, however each of those examples returns null.

I'm assuming this can be done within the pattern somehow and not the quantifier, so I'd like to understand how that would be written with .match(). Or would this require having to write a custom method that would involve other string manipulation in order to accomplish this?

like image 202
Robert Wade Avatar asked Dec 04 '17 19:12

Robert Wade


2 Answers

Regular expressions always match from left to right, but you can use a positive lookahead with an end-of-string anchor to achieve what you want:

var foo = "ABCDEFG";
foo.match(/.{1,3}(?=(.{3})*$)/g);  // ["A", "BCD", "EFG"]

Here the subpattern (?=(.{3})*$) is a lookahead expression that matches zero or more repetitions of (exactly!) 3 characters, bounded at the end of the string ($).

like image 72
GOTO 0 Avatar answered Oct 26 '22 23:10

GOTO 0


As stated in comments there's no regex or quantifier that matches your string from backwards reading from right to left.

What you can do here is to reverse the string before calling .match() then reverse the matches array:

var matches = foo.split("").reverse().join("")
    .match(/.{1,3}/g).map(m => m.split("").reverse().join(""))
    .reverse();

Explanation:

  • We use foo.split("").reverse().join("") to reverse the original string.
  • Then call .match() with this reversed string.
  • Reverese the matches with .map(m => m.split("").reverse().join("")).
  • And finally reverse the matches array.

Demo:

var foo = "ABCDEFG";

var matches = foo.split("").reverse().join("").match(/.{1,3}/g).map(m => m.split("").reverse().join("")).reverse();
console.log(matches);
like image 36
cнŝdk Avatar answered Oct 27 '22 00:10

cнŝdk