I would like to check if f.e letter "a" occurs between 3 and 5 times (inclusive), in total, within provided text input.
Given:
zayaaxaawv
<- 5 of "a", passedzayaxawva
<- 4 of "a", passedzaaay
<- 3 of "a", passedzayax
<- 2 of "a", failedzayaaxaaaw
<- 6 of "a", failedExamples 1-3 passed and 4-5 failed.
I know it can be done in JavaScript without using RegExp
, f.e:
const txt = `zayaxawva`;
const charCountByFilter = [...txt].filter(letter => letter === 'a').length;
const charCountByMatch = txt.match(/a/g).length;
console.log('isInRange by filter', isInRange(charCountByFilter));
console.log('isInRange by match', isInRange(charCountByMatch));
function isInRange(value) {
return value >= 3 && value <= 5;
}
However, is it possible to do it entirely by RegExp? I thought of something similar to/a{3,5}/.test(txt)
, but it only counts subsequent "a" chars, not all of them.
You can use
^(?:[^a]*a){3,5}[^a]*$
See the regex demo. Details:
^
- start of a string anchor(?:[^a]*a){3,5}
- a non-capturing group matching three, four or five occurrences of
[^a]*
- zero or more chars other than a
a
- an a
char[^a]*
- zero or more chars other than a
$
- end of the string anchor.See the JavaScript demo:
const strings = ['zayaaxaawv','zayaxawva','zaaay','zayax','zayaaxaaaw'];
const l = 'a', min = 3, max = 5;
const rx = new RegExp(`^(?:[^${l}]*${l}){${min},${max}}[^${l}]*$`);
strings.forEach(x => console.log(x, '=>', rx.test(x)));