matching regex pattern for different cards

Viewed 105

I have 4 different regex pattern matchers and corresponding replace strings. Inside my java code, I check for each regex and replace with the value. Is there anyway I can consolidate in single regex and single replace string?

DISC_CARD=(\\W|000)(6(?:011|5[0-9]{2})[0-9]{8})([0-9]{4}\\D)
MAST_CARD=(\\W|000)((?:5[0-9]{3}|2[2-7][0-9]{2})[0-9]{8})([0-9]{4}\\D)    
VISA_CARD=(\\W|000)(4[0-9]{11})([0-9]{4}\\D)
AMEX_CARD=(\\W|000)(3[47][0-9]{9})([0-9]{4}\\D)

DISC_MASK=$1XXXXXXXXXXXX$3
MAST_MASK=$1XXXXXXXXXXXX$3
VISA_MASK=$1XXXXXXXXXXXX$3
AMEX_MASK=$1XXXXXXXXXXX$3

Java code:

for (int i = 0; i < regPatterns.size(); i++) {
  message = regPatterns.get(i).matcher(message).replaceAll(maskPatterns[i]);
}
1 Answers

You may use alternation to combine all your given regex. Something like:

^(\W|000)((?<Disc>6(?:011|5[0-9]{2})[0-9]{8})|(?<Mast>(?:5[0-9]{3}|2[2-7][0-9]{2})[0-9]{8})|(?<Visa>4[0-9]{11})|(?<Amex>3[47][0-9]{9}))([0-9]{4}\D)$

Breaking down the above regex:

  • ^, $ - Represents start and end of the line respectively.
  • (\W|000) - Represents your first capturing group.
  • (?<Disc>(6(?:011|5[0-9]{2})[0-9]{8}) - Represents your DISC_Card validation regex.
  • | - Represents alternation.
  • (?<Mast>(?:5[0-9]{3}|2[2-7][0-9]{2})[0-9]{8}) - Represents your MAST_CARD validation regex group.
  • (?<Visa>4[0-9]{11}) - Represents your VISA_CARD validation regex group.
  • (?<Amex>3[47][0-9]{9})) - Represents your AMEX_CARD validation regex group.
  • ([0-9]{4}\D) - Represents your 3rd capturing group.(But as per new regex it is 7th capturing group.)
  • NOTE: I used named capturing group in order to differentiate between them and to make them more legible.

You can find the demo of the above regex in here.

Sample Implementation in java:(Please do implement the code according to your requirement.)

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main{
    // Regex pattern
    private static final Pattern pattern = Pattern.compile("^(\\W|000)((?<Disc>6(?:011|5[0-9]{2})[0-9]{8})|(?<Mast>(?:5[0-9]{3}|2[2-7][0-9]{2})[0-9]{8})|(?<Visa>4[0-9]{11})|(?<Amex>3[47][0-9]{9}))([0-9]{4}\\D)$", Pattern.MULTILINE);
    // final array of strings to replace(First element for all the three and second element for the last one i.e. Amex Card)
    private static final String[] replacementStrings = {"$1xxxxxxxxxxxx$7", "$1xxxxxxxxxxx$7"};
   
    public static void main(String[] args){
        // Input String
        String str = "0006011123456781114D\n000341234567891234D\n0002421123456787891D\n0004123456789012346R\nTHisWOntMAtch";
        for(String st : str.split("\n")){
            System.out.println(getMaskedCardDetail(st));
        }
    }
    // Utility Method for provide Masking of card details.
    private static String getMaskedCardDetail(String givenString){
        Matcher matcher = pattern.matcher(givenString);
        if(matcher.matches()){
            String temp = "";
            if(matcher.group("Disc") != null || matcher.group("Mast") != null || matcher.group("Visa") != null) 
                temp = matcher.replaceAll(replacementStrings[0]);
            else 
                temp = matcher.replaceAll(replacementStrings[1]);
            return temp;    
        }else{
            return "NO MATCH";
        }
    }
}
/*
Output: 
000xxxxxxxxxxxx1114D                                                                                                                          
000xxxxxxxxxxx1234D                                                                                                                           
000xxxxxxxxxxxx7891D                                                                                                                          
000xxxxxxxxxxxx2346R                                                                                                                          
NO MATCH
*/

You can find the sample run result of the above implementation in here.

Related