Regex для маскировки номера кредитной карты и счета

Мне нужно замаскировать кредитную карту (если цифры >= 12 и <= 19) и номер счета (если цифры == 8 или 9). Ниже должен быть ввод/вывод для различных строк:

123456789123 -> ххххххх9123

1234-5678-9123-4567 -> хххх-хххх-хххх-4567

1234-5678-9123-4567-891 --> хххх-хххх-хххх-xxx7-891

123123123123131Для8640 --> xxxxxxxxxx3131Для8640

123123123123131to123123123123177 --> xxxxxxxxxxx3131toxxxxxxxxxxxx3177

12345678 --> хххх5678

Я плачу 2700 долларов с помощью кредитной карты (123456789012345) на свой счет (12345678) --> Я плачу 2700 долларов с помощью кредитной карты (xxxxxxxxxxxx2345) на свой счет (xxxx5678).

Обратите внимание, что в любом случае должны быть видны только последние 4 цифры (включая дефис).

Приведенный ниже код работает во всех случаях, за исключением случаев, когда номер кредитной карты имеет нечетное общее количество цифр. Например, 13,15 или 19. Этот случай не работает с кодом ниже -->

Ожидается: 1234-5678-9123-4567-891 --> xxxx-xxxx-xxxx-xxx7-891
Актуально: 1234-5678-9123-4567-891 --> xxxx-xxxx-xxxx-xxxx-891.

private static string MaskIfAccountNumber(this string text)
{
    if (string.IsNullOrEmpty(text))
        return text;

    return Regex.Replace(text, "[0-9][0-9 ]{6,}[0-9]", match =>
    {
        string digits = string.Concat(match.Value
          .Where(c => char.IsDigit(c)));

        return digits.Length == 8 || digits.Length == 9
          ? new string('x', digits.Length - 4) + digits.Substring(digits.Length - 4)
          : match.Value;
    });
}
public static string MaskIfContainCreditCardPanorAcctNum(this string value)
{
    if (string.IsNullOrEmpty(value))
        return value;

    var maskedAccountNumber = value.MaskIfAccountNumber();

    return MaskCreditCardNo(maskedAccountNumber);
}

public static string MaskCreditCardNo(this string value)
{
    if (string.IsNullOrWhiteSpace(value))
        return value;

    return Regex.Replace(value, "(\\d[\\s|-]?){10,}\\d", match =>
        {
            string CCnumber = match.Value;
            string digits = string.Concat(CCnumber
         .Where(c => char.IsDigit(c)));
            return (digits.Length >= 12 && digits.Length <= 19) ?
            Regex.Replace(CCnumber.Substring(0, CCnumber.Length - 4), @"\d", "x") + CCnumber.Substring(CCnumber.Length - 4) : match.Value;
        });
}

«не работает» — недостаточное описание проблемы. Что происходит в отличие от того, что вы хотите?

Fildor 15.05.2024 07:51

Номер любой кредитной карты. сумма нечетных цифр (13,17,19), например, 1234-5678-9123-4567-891 преобразуется в xxxx-xxxx-xxxx-xxxx-891. Это неверно. В любом случае должны быть видны последние 4 цифры вместе с дефисом (-). Таким образом, правильный вывод должен быть xxxx-xxxx-xxxx-xxx7-891. Любое изменение в схеме может повлиять на другие упомянутые сценарии.

user3665818 15.05.2024 07:57

Я думаю, вы могли бы избавить себя от головной боли Regex, внедрив поддерживаемое решение: dotnetfiddle.net/jnGyfa

Fildor 15.05.2024 08:58

@Fildor: Мне это нравится гораздо больше. И как обычно: у разработчика проблема. Она пытается решить эту проблему с помощью RegEx. Теперь у разработчика есть две проблемы.

Oliver 15.05.2024 13:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
81
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать шаблон положительного просмотра назад, чтобы утверждать, что совпадающая цифра находится в пределах от 12 до 19 последовательных цифр, которым предшествует необязательное тире, и использовать шаблон отрицательного просмотра назад, чтобы утверждать, что за совпадающей цифрой не следуют 3 или менее цифр:

(?<=(?<![\d-])(?=(?:-?\d){12,19}(?![\d-]))[\d-]*)\d(?!(?:-?\d){0,3}(?![\d-]))

Демо: https://regex101.com/r/e0o6Zf/1

Привет @blhsing, мне также нужно сопоставить * с 12-19 цифрами. Таким образом, строка «521893******8699» должна выглядеть как «xxxxxxxxxxxx8699». Как я могу добиться этого с помощью вашего регулярного выражения, на которое вы ответили выше?

user3665818 30.05.2024 07:08

Замена всех \d на [\d*] сделает: regex101.com/r/e0o6Zf/2

blhsing 30.05.2024 07:13

Спасибо. Оно работает. И последнее, если вы не возражаете. Как я могу включить пробелы? Таким образом, для строки типа «1234 5678 9123 4567» она должна быть xxxx xxxx xxxx 4567.

user3665818 30.05.2024 07:41

Вы можете заменить все - на [ -], но тогда номер кредитной карты не должен смешиваться с другими пробелами, иначе станет неясно, принадлежит ли пробел номеру кредитной карты или остальной части предложения: regex101.com/r/e0o6Zf /3

blhsing 30.05.2024 07:53

Спасибо. Я попробовал использовать \s, и вроде тоже все в порядке. dotnetfiddle.net/Gopzoz#

user3665818 30.05.2024 07:59

Привет. Я думаю, что то, что вы упомянули об изменениях пространства в своем последнем комментарии, теперь стало понятным. Я не получаю правильный вывод для «Тест 123456789123 Тест». Он должен выглядеть как «Тест xxxxxxxxx9123 Test». Если я внесу какие-либо изменения в регулярное выражение, это нарушит другие существующие сценарии — dotnetfiddle.net/Gopzoz#. Можно ли что-то сделать, чтобы справиться с этим? Если хотите, я могу задать новый вопрос. Спасибо

user3665818 03.06.2024 04:12

Извини. Пожалуйста, игнорируйте это. Работает.

user3665818 03.06.2024 04:28

Привет. У меня возникает проблема со строкой типа «Расписание Pmt — перевод на номер 183000004». Здесь 183000004 — это, по сути, номер счета, который может состоять из 8 или 9 цифр. Но поскольку перед номером счета есть «пробел», он не маскирует его под «Расписание Pmt — перевод на xxxxx0004». Пожалуйста, обратитесь к dotnetfiddle.net/Gopzoz#. Спасибо

user3665818 12.06.2024 07:44

Если номер счета не должен содержать пробел, не включайте его в шаблон: regex101.com/r/mX0emt/1

blhsing 12.06.2024 08:18

Привет @blhsing. У меня возникла проблема, когда в CreditCardNo есть пробел до/после. Например, «от INV 2420852290 до SAV 0165487». Здесь 2420852290 состоит из 10 цифр, но он маскируется. Для номера кредитной карты диапазон составляет 12–19 цифр. Причина в пробеле (до или после цифр), который, я думаю, занимает дополнительный 11-й или 12-й символ. Используемое регулярное выражение: "(?<=(?<![\d-])(?=(?:-?[\d*\s]){12,19}(?![\d-*\ s]))[\d-*\s])‌​[\d*](?!(?:-?[\d*\s]‌​){0,3}(?![\d- *\s]))"‌​. dotnetfiddle.net/Gopzoz#. Пожалуйста, помогите, если это возможно. Кроме того, потребуется место для CCNo, например 1234 5678 9123 4567.

user3665818 22.07.2024 06:55

Я также создал новый вопрос для этих сценариев — stackoverflow.com/questions/78777023/…

user3665818 22.07.2024 07:12

Другие вопросы по теме