提问人:Vito 提问时间:10/17/2023 最后编辑:Wiktor StribiżewVito 更新时间:10/20/2023 访问量:165
在 C 语言中屏蔽 IBAN 代码#
Masking IBAN codes in C#
问:
我有一些IBAN代码。例如,它是德国 IBAN:.我需要掩盖它并得到这样的结果:.但是,由于每个国家/地区的IBAN长度都不同,因此我有以下屏蔽规则:.因此,如果 DE IBAN - ,如果 BE .DE12500123456789012345
DE*****12345*******345
{2 letters}{5 asterisks}{5 numbers}{n asterisks}{3 numbere}
DE*****12345*******345
BE*****12345*345
如何使用 C# 的正则表达式实现它?
答:
-1赞
Eldar
10/17/2023
#1
好吧,在您的情况下,不使用正则表达式会更容易、性能更高:
var iban = "DE12500123456789012345";
var maskedIban = $"{iban[0..2]}{"".PadRight(5, '*')}{iban[7..12]}{"".PadRight(iban.Length -15, '*')}{iban[^3..]}";
// ^ "DE*****12345*******345"
编辑一个不像上面那么干净的正则表达式解决方案,它使用命名组和修改后的扩展方法,该方法替换了从此 SO 答案中获取的命名组
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 | 7520 字节 |
PureConcat的 | DE125(...)12345 [22] | 154.3纳秒 | 2.39纳秒 | 2.66纳秒 | 0.0223 | 240 字节 |
纯正则表达式 | DE125(...)12345 [22] | 7,639.8纳秒 | 67.17纳秒 | 68.98纳秒 | - | 72 字节 |
评论
1赞
Vito
10/17/2023
也是好点,但正如我所说,我需要用正则表达式来做。多谢
0赞
Vito
10/17/2023
实际上,我已经按照你的建议做了。但是如何检查不同方法的性能呢?当然,当您的方法具有更好的性能时,我会使用它
0赞
Eldar
10/17/2023
@Vito添加了正则表达式选项和性能比较
-1赞
Vlam
10/17/2023
#2
此正则表达式示例应适用于 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);
}
}
}
评论
0赞
Eldar
10/17/2023
这仍然使用字符串连接。你可以用填充来代替这个:string.Concat(Enumerable.Repeat("*",match.Groups[3].Value.Length))
评论
*
Regex.Replace(text, @"(?<=^[A-Z]{2}(?:\d{0,4}|\d{10,}(?=\d{4,}$)))\d", "*")