在 C 语言中屏蔽 IBAN 代码#

Masking IBAN codes in C#

提问人:Vito 提问时间:10/17/2023 最后编辑:Wiktor StribiżewVito 更新时间:10/20/2023 访问量:165

问:

我有一些IBAN代码。例如,它是德国 IBAN:.我需要掩盖它并得到这样的结果:.但是,由于每个国家/地区的IBAN长度都不同,因此我有以下屏蔽规则:.因此,如果 DE IBAN - ,如果 BE .DE12500123456789012345DE*****12345*******345{2 letters}{5 asterisks}{5 numbers}{n asterisks}{3 numbere}DE*****12345*******345BE*****12345*345

如何使用 C# 的正则表达式实现它?

C# 字符串 掩码

评论

0赞 Dai 10/17/2023
正则表达式用于匹配,而不是“屏蔽”——但如果你想使用正则表达式匹配的结果来确定要替换哪些字符(用字符),那么这很好,但你需要将这两个步骤分开,而不是将它们混为一谈。*
0赞 Eldar 10/17/2023
你根本不需要正则表达式。但是您需要澄清的是,您将显示的数字是恒定的,星号是可变的,对吗?
0赞 Vito 10/17/2023
我是这样做的:string iban = “DE1250012345678901234”;字符串模式 = @“(\d{2})(?=.{3})";string result = Regex.Replace(iban, pattern, m => new string('*', m.Length));但结果是 DE****************234。我知道我必须延长父权,但不知道该怎么做
0赞 Vito 10/17/2023
@Eldar,遮罩后应该有可见的前两个字母,8-12 个数字和最后 3 个数字
1赞 Wiktor Stribiżew 10/17/2023
正则表达式方式可能只是一个Regex.Replace(text, @"(?<=^[A-Z]{2}(?:\d{0,4}|\d{10,}(?=\d{4,}$)))\d", "*")

答:

-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))