Home > Software design >  Regex javascript match the second letter by the first letter, but the second letter must be an upper
Regex javascript match the second letter by the first letter, but the second letter must be an upper

Time:05-20

This regex matches the second letter by the first letter, but the second letter is not an uppercase

([a-z])\1

Now regex matches letters like aa or bb,... but I need that my regex can match all aA,bB,... from this string "abcaAcvbBklmM"

So how to make that regex can match the second value by the first value, but the second must be an uppercase

CodePudding user response:

You could phrase this by matching all [a-z]\1 in lowercase mode and then checking if each match also matches [a-z][a-Z]:

var input = "abcaAcvbBklmMzzQQ";
var matches = input.match(/([a-z])\1/gi)
                   .filter(x => /^[a-z][A-Z]$/.test(x));
console.log(matches);

CodePudding user response:

It's ugly as, but if you must use a simple regex, you could just brute-force the full set of pairings:

var myText = "aAaaABbCCddEEeEfF";
var letterPairs = myText.match(/aA|bB|cC|dD|eE|fF|gG|hH|iI|jJ|kK|lL|mM|nN|oO|pP|qQ|rR|sS|tT|uU|vV|wW|xX|yY|zZ/g);
console.log(letterPairs);

It doesn't feel very satisfactory as a solution, but it'll get the job done.

CodePudding user response:

I don't think you can do this with just a JavaScript regular expression (well, not unless you list all possible combinations). Regular expressions in some other environments may be able to do it, but not JavaScript's.

It's fairly straight-forward, though, to match a lower-case character followed by an upper-case character and then filter out ones where the one isn't the lower-case equivalent of the other:

const str = "abcaAcvbBklmM";

const results = [];
for (const [, lower, upper] of str.matchAll(/([a-z])([A-Z])/g)) {
    if (lower === upper.toLocaleLowerCase()) {
        results.push(lower   upper);
    }
}

console.log(results);

How that works:

  • The regular expression /([a-z])([A-Z])/g matches a lower-case letter followed by an upper-case letter (but they aren't necessarily the "same" letter), capturing each in a capture group.
  • matchAll matches all occurrences of that in a string, returning an iterator for the results.
  • The for-of loop loops through the results from the iterator. The results from matchAll are an augmented array,¹ where the first element in the array is the overall match, followed by elements for any capture groups. The code uses destructuring in the for-of to pick out the second and third elements of the array (the two capture groups).
  • If the first letter matches the second letter converted to lower case, it's a match and we retain it.

We can also do this with multiple passes using array methods rather than a single for-of:

const str = "abcaAcvbBklmM";

const results = [...str.matchAll(/([a-z])([A-Z])/g)]
    .filter(([, lower, upper]) => lower === upper.toLocaleLowerCase())
    .map(([match]) => match);

console.log(results);


¹ This code isn't using the augmented parts of the array, but basically it addition to being an array it has an index property saying where the match occurred, a groups property containing capture group information (which we could have used, but it was just as easy to use the array elements for this simple regex), and an input property with the original string.

CodePudding user response:

You could use the capture group with the backreference and make the pattern case insensitive with the /i flag.

Then compare the matched string with the expected lower and uppercase variants.

const input = "yyabcaAcvbBklmMzzQQ";
const regex = /([a-z])\1/ig;

const matches = input.match(regex)
  .filter(s =>
    s[0].toLowerCase()   s[1].toUpperCase() === s
  )

console.log(matches);

  • Related