Java Regex — маска номера кредитной карты

#java #regex #string

#java #Регулярное выражение #строка

Вопрос:

У меня есть функция, которая маскирует номера кредитных карт в строке:

   public static String  replaceCreditCardNumber(String text){
         final String MASKCARD = "$1<MASKED>$2";
         final Pattern PATTERNCARD = 
            Pattern.compile("([0-9]{4})[0-9]{0,9}([0-9]{4})");    
         Matcher matcher = PATTERNCARD.matcher(text);
         if (matcher.find()) {
             return   matcher.replaceAll(MASKCARD);
         }
         return text;

    }
  

эта функция отлично работает в следующих случаях:

     String text = "Aaaa bbbb aaa=1234567890123456 fdfdfd=aaa";
    String expected = "Aaaa bbbb aaa=1234<MASKED>3456 fdfdfd=aaa";
    assertEquals(expected,text);//OK

    String text = "Aaaa bbbb aaa="1234567890123456" fdfdfd=aaa";
    String expected = "Aaaa bbbb aaa="1234<MASKED>3456" fdfdfd=aaa";
    assertEquals(expected,text);
  

Однако в следующем случае происходит сбой

         String text = "Aaaa bbbb aaa=1gfg23fgfg4567890123456 fdfdfd=aaa";
        String expected = "Aaaa bbbb aaa=1gfg23fgfg4567890123456 fdfdfd=aaa";
        assertEquals(expected,text);
  

Я получаю

         aaa=1gfg23fgfg4567[<MASKED>]3456
  

Чего мне не хватает в моем регулярном выражении?

Комментарии:

1. Почему у вас [0-9]{0,9} посередине? Разве номер кредитной карты не всегда состоит из 16 цифр?

2. Вы запрашиваете 4 цифры, затем до девяти цифр и еще 4 цифры — и это то, что у вас есть в случае «сбоя». Поэтому средние 5 цифр заменяются. Вам нужно иметь 8 цифр для маскировки?

3. @Keppli — не совсем — у них тоже может быть 14 (Diners Club) или 15 (American Express). Некоторые визы даже имеют 13. Вот ресурс, который включает в себя некоторые предложения по регулярным выражениям кредитных / дебетовых карт

4. @Vld: Хорошо, тогда это [0-9]{5,8} может иметь больше смысла.

Ответ №1:

Вы должны использовать границы слов, чтобы избежать сопоставления нежелательного ввода:

 final Pattern PATTERNCARD = 
        Pattern.compile("\b([0-9]{4})[0-9]{0,9}([0-9]{4})\b"); 
  

Рабочая демонстрация

Ответ №2:

На основе примеров:

 Pattern.compile("([0-9]{4})[0-9]{8}([0-9]{4})");
  

Ответ №3:

Я надеюсь служить вам

У меня есть следующий класс:

     public class PatternCreditCard {

  // ------------------------- PATTERN DEFINE TYPE CREDIT --------------------------- //
  public static final String VISA = "^4.*";
  public static final String VISA_ELECTRON = "^(4026|417500|4508|4844|491(3|7)).*";
  public static final String MASTER_CARD = "^5[1-5].*";
  public static final String AMEX = "^3[47].*";
  public static final String DISCOVER =
      "^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65).*";
  public static final String DINERS = "^36.*";
  public static final String DINERS_CARTE_BLANCHE = "^30[0-5].*";
  public static final String JCB = "^35(2[89]|[3-8][0-9]).*";

  // ------------------------- PATTERN SEPARATOR GROUP NUMBERS --------------------------- //
  public static final String VISA_SEPARATOR =
      "^([0-9 ]{5})([0-9 ]{5})?([0-9 ]{5})?(?:([0-9 ]{5})([0-9 ]{5})?([0-9]{5})([0-9]{4}))?$";

  public static final String MASTER_CARD_SEPARATOR =
      "^([0-9 ]{5})([0-9 ]{5})?([0-9 ]{5})?(?:([0-9 ]{5})([0-9 ]{5})?([0-9]{5})([0-9]{4}))?$";

  public static final String AMEX_SEPARATOR =
      "^([0-9 ]{5})([ ]?[0-9 ]{7})?(?:([ ]?[0-9 ]{7})([ ]?[0-9]{5}))?$";

  public static final String DISCOVER_SEPARATOR =
      "^([0-9 ]{5})([0-9 ]{5})?([0-9 ]{5})?(?:([0-9 ]{5})([0-9 ]{5})?([0-9]{5})([0-9]{4}))?$";

  // ------------------------- LENGTH PERMITTED FOR CREDIT CARD --------------------------- //
  public static final int VISA_LEN = 16;
  public static final int MASTER_CARD_LEN = 16;
  public static final int AMEX_LEN = 15;
  public static final int DISCOVER_LEN = 16;

}
  

затем выполните замену строки номера кредитной карты, если возвращаемое значение равно «» (пустое): означает, что строка соответствует любой группе в регулярном выражении.

 cardNumber.replaceAll(VISA_SEPARATOR, " ");