Reputation: 11
Regex newbie here. I'm trying to write an expression that matches the last two (or n) separate spaces.
v v
This is a test
I have an ultra simple expression that returns the last space:
/ (?=[^ ]*$)/i
but cannot seem to figure out how to get it to return twice and only twice (or n times)
Upvotes: 1
Views: 268
Reputation: 163277
You might also match a space and assert using a positive lookahead that there is an optional space to the right.
Denoted the space between square brackets just for clarity.
[ ](?=(?:\S+ ){0,1}\S+$)
[ ]
Match a space(?=
Positive lookahead, assert that on the right it
(?:\S+ ){0,1}
Match 0 or 1 non whitespace chars followed by a space\S+
Match 1+ non whitespace chars$
End of string)
Close lookaheadIn the pattern, the quantifier {0,1}
lets you specify the amount of spaces to match.
Using {0,2}
will match the last 3 spaces, and using {0}
will match only the last space.
If there can also be optional spaces at the end:
[ ](?=(?:\S+ ){0,1}\S+ *$)
Upvotes: 0
Reputation: 350167
You could use a negative lookahead that will require that there are not two spaces somewhere after the candidate space:
let s = "This is a test";
let result = s.replace(/ (?!.* .* )/gs, "°");
console.log(result);
I must say that this has a bad time complexity. For large strings you will get better performance with lastIndexOf
:
let s = "This is a test";
s = " " + s; // Add dummies to avoid boundary cases
let last = s.lastIndexOf(" ");
let prev = s.lastIndexOf(" ", last - 1);
// Replace those spaces:
let result = s.slice(0, prev) + "°" + s.slice(prev+1, last) + "°" + s.slice(last+1);
// Remove the dummies:
result = result.slice(2);
console.log(result);
Upvotes: 1