我有一些 IBAN 代码。例如,德国 IBAN:
DE12500123456789012345
。我需要掩盖它并得到这样的结果:DE*****12345*******345
。但由于每个国家/地区的 IBAN 长度不同,我有以下屏蔽规则:{2 letters}{5 asterisks}{5 numbers}{n asterisks}{3 numbere}
。因此,如果是 DE IBAN - DE*****12345*******345
,如果是 BE BE*****12345*345
。
如何使用 C# 的 Regex 实现它?
在您的情况下,不使用正则表达式会更容易、更高效:
var iban = "DE12500123456789012345";
var maskedIban = $"{iban[0..2]}{"".PadRight(5, '*')}{iban[7..12]}{"".PadRight(iban.Length -15, '*')}{iban[^3..]}";
// ^ "DE*****12345*******345"
编辑 正则表达式解决方案不像上面那样干净,它使用命名组和修改后的扩展方法来替换从此SO中获取的命名组answer
public static class X
{
public static string ReplaceGroup(this Regex regex, string input, string groupName, char pattern)
{
return regex.Replace(input, m =>
{
var group = m.Groups[groupName];
var sb = new StringBuilder();
var previousCaptureEnd = 0;
foreach (var capture in group.Captures.Cast<Capture>())
{
var currentCaptureEnd = capture.Index + capture.Length - m.Index;
var currentCaptureLength = capture.Index - m.Index - previousCaptureEnd;
sb.Append(m.Value.Substring(previousCaptureEnd, currentCaptureLength));
sb.Append("".PadRight(currentCaptureLength,pattern));
previousCaptureEnd = currentCaptureEnd;
}
sb.Append(m.Value.Substring(previousCaptureEnd));
return sb.ToString();
});
}
}
// Usage
var input = "DE12500123456789012345";
var groupPattern = @"^([A-Z]{2})(?<Ast>\d{5})(\d{5})(?<Ast>.*)(\d{3})$";
var groupRegex = new Regex(groupPattern);
var x = groupRegex.ReplaceGroup(input,"Ast", '*');
编辑 在基准测试中添加了 @Wiktor Stribiżew 解决方案:
Regex.Replace(text, @"(?<=^[A-Z]{2}(?:\d{0,4}|\d{10,}(?=\d{4,}$)))\d", "*")
三种方法的性能对比:
方法 | 伊班 | 意思是 | 错误 | 标准偏差 | 0代 | 已分配 |
---|---|---|---|---|---|---|
正则表达式连接 | DE125(...)12345 [22] | 7,492.0 纳秒 | 532.88 纳秒 | 592.29纳秒 | 0.6457 | 7520B |
纯康卡特 | DE125(...)12345 [22] | 154.3纳秒 | 2.39 纳秒 | 2.66 纳秒 | 0.0223 | 240B |
纯正则表达式 | DE125(...)12345 [22] | 7,639.8 纳秒 | 67.17 纳秒 | 68.98 纳秒 | - | 72B |
这个正则表达式示例应该适用于 DE 和 BE 情况。
using System;
using System.Text.RegularExpressions;
using System.Linq;
class Example
{
static void Main()
{
string input = "DE12500123456789012345";
string pattern = @"^([A-Z]{2})(?:.{5})(\d{5})(.*)(\d{3})$";
MatchCollection matches = Regex.Matches(input, pattern);
foreach (Match match in matches)
{
Console.Write("{0}*****", match.Groups[1].Value);
Console.Write("{0}", match.Groups[2].Value);
Console.Write("{0}", string.Concat(Enumerable.Repeat("*",match.Groups[3].Value.Length)));
Console.WriteLine("{0}", match.Groups[4].Value);
}
}
}