Мне нужно замаскировать кредитную карту (если цифры >= 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;
});
}
Номер любой кредитной карты. сумма нечетных цифр (13,17,19), например, 1234-5678-9123-4567-891 преобразуется в xxxx-xxxx-xxxx-xxxx-891. Это неверно. В любом случае должны быть видны последние 4 цифры вместе с дефисом (-). Таким образом, правильный вывод должен быть xxxx-xxxx-xxxx-xxx7-891. Любое изменение в схеме может повлиять на другие упомянутые сценарии.
Я думаю, вы могли бы избавить себя от головной боли Regex, внедрив поддерживаемое решение: dotnetfiddle.net/jnGyfa
@Fildor: Мне это нравится гораздо больше. И как обычно: у разработчика проблема. Она пытается решить эту проблему с помощью RegEx. Теперь у разработчика есть две проблемы.





Вы можете использовать шаблон положительного просмотра назад, чтобы утверждать, что совпадающая цифра находится в пределах от 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». Как я могу добиться этого с помощью вашего регулярного выражения, на которое вы ответили выше?
Замена всех \d на [\d*] сделает: regex101.com/r/e0o6Zf/2
Спасибо. Оно работает. И последнее, если вы не возражаете. Как я могу включить пробелы? Таким образом, для строки типа «1234 5678 9123 4567» она должна быть xxxx xxxx xxxx 4567.
Вы можете заменить все - на [ -], но тогда номер кредитной карты не должен смешиваться с другими пробелами, иначе станет неясно, принадлежит ли пробел номеру кредитной карты или остальной части предложения: regex101.com/r/e0o6Zf /3
Спасибо. Я попробовал использовать \s, и вроде тоже все в порядке. dotnetfiddle.net/Gopzoz#
Привет. Я думаю, что то, что вы упомянули об изменениях пространства в своем последнем комментарии, теперь стало понятным. Я не получаю правильный вывод для «Тест 123456789123 Тест». Он должен выглядеть как «Тест xxxxxxxxx9123 Test». Если я внесу какие-либо изменения в регулярное выражение, это нарушит другие существующие сценарии — dotnetfiddle.net/Gopzoz#. Можно ли что-то сделать, чтобы справиться с этим? Если хотите, я могу задать новый вопрос. Спасибо
Извини. Пожалуйста, игнорируйте это. Работает.
Привет. У меня возникает проблема со строкой типа «Расписание Pmt — перевод на номер 183000004». Здесь 183000004 — это, по сути, номер счета, который может состоять из 8 или 9 цифр. Но поскольку перед номером счета есть «пробел», он не маскирует его под «Расписание Pmt — перевод на xxxxx0004». Пожалуйста, обратитесь к dotnetfiddle.net/Gopzoz#. Спасибо
Если номер счета не должен содержать пробел, не включайте его в шаблон: regex101.com/r/mX0emt/1
Привет @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.
Я также создал новый вопрос для этих сценариев — stackoverflow.com/questions/78777023/…
«не работает» — недостаточное описание проблемы. Что происходит в отличие от того, что вы хотите?