Reputation: 11482
I have implemented this regex for matching a string for validation purposes:
^(?<serialCode>[a-zA-Z0-9]{0,3})(?:(?<serialMarket>[a-zA-Z]{1,2})(?<serialSuffix>(?<=^.{5})[a-zA-Z0-9]*)?)?
I'm using it in JS using match()
function like this:
const regex = '^(?<serialCode>[a-zA-Z0-9]{0,3})(?:(?<serialMarket>[a-zA-Z]{1,2})(?<serialSuffix>(?<=^.{5})[a-zA-Z0-9]*)?)?';
const stringToMatch = 'EV1FOO12FF344';
const result = stringToMatch.match(new RegExp(regex));
console.log(result); // returns each group for match and also the full match
What basically this does is that it's doing the following step by step validations and creating groups:
This validation is done for every typed value in an input field, character by character.
Using lookbehind as you can see above, this works perfectly for my purposes in Chrome and Mozilla Firefox browsers.
The problem: lookbehind
(in current case (?<=^.{5})
) is not supported on Safari browser as per this link: https://caniuse.com/js-regexp-lookbehind We receive this error in this case: Invalid regular expression: invalid group specifier name
Is there any alternative to that lookbehind so the regex will work in the exact same way?
I have the link where I tested some values for exemplification: https://regex101.com/r/fPmiTk/1 There you can see how the strings are matched and how the groups are created.
Upvotes: 4
Views: 5788
Reputation: 626927
I doubt there is a way with a single regex with no lookbehind or conditionals support thus I suggest the following approach combining regex and additional programming logic:
var texts = ['abcfobar','abc33bar'];
var regex = /^([a-zA-Z0-9]{0,3})(?:([a-zA-Z]{1,2})([a-zA-Z0-9]+)?)?/;
for (var i=0; i<texts.length;i++) {
var serialCode = '';
var serialMarket = '';
var serialSuffixmatch = '';
var match = texts[i].match(regex);
if (match) {
serialCode = match[1];
serialMarket = (match[2] || "");
if (serialCode.length == 3 && serialMarket.length == 2) {
serialSuffixmatch = match[3];
}
}
console.log(texts[i], '=>', serialCode + "\n" + serialMarket + "\n" + serialSuffixmatch);
}
That is, simply use numbered capturing groups, and once a match is obtained, check the length of the first and second groups, and if the sum of their lengths is 5, grab Group 3 value, too.
Upvotes: 2
Reputation: 20737
You can use a conditional to start with your most restrictive pattern and work your way backwards to the least restrictive one:
^(?:[a-zA-Z0-9]{3}[a-zA-Z]{2}[a-zA-Z0-9]*|[a-zA-Z0-9]{3}[a-zA-Z]{1,2}|[a-zA-Z0-9]{0,3})
I don't know if the named capture groups have any significance for your JS code logic but unfortunately you cannot declare the same capture group name.
https://regex101.com/r/2uztK5/1
Upvotes: 1