屏蔽除字符串的前6位和后4位以外的所有数字(长度各不相同)

我有一个卡号作为字符串,例如:

string ClsCommon.str_CardNumbe r = "3456123434561234"; 

此卡号的长度可以在16到19位之间变化,具体取决于要求。

我的要求是我必须显示卡号的前六位和后四位,并用字符“X”掩盖其中的其他字符。

我尝试过使用subString并分别为16,17,18,19位数实现它。

我将字符串(ClsCommon.str_CardNumber)拆分为5个字符串(str_cardNum1,str_cardNum2,str_cardNum3,str_cardNum4,str_cardNum5 – 每个字符串4位数。第5个字符串的剩余数字)

所有字符串都放在ClsCommon文件中。 基于此我实现了以下,它完美地工作:

 if (ClsCommon.str_CardNumber.Length == 16) { txtmskcrdnum.Text = string.Concat(ClsCommon.str_cardNum1, " ", ClsCommon.str_cardNum2.Substring(0, 2), "XX", " ", "XXXX", " ", ClsCommon.str_cardNum4); } if (ClsCommon.str_CardNumber.Length == 17) { txtmskcrdnum.Text = string.Concat(ClsCommon.str_cardNum1, " ", ClsCommon.str_cardNum2.Substring(0, 2), "XX", " ", "XXXX", " ", "X", ClsCommon.str_cardNum4.Substring(1, 3), " ", ClsCommon.str_cardNum5); } if (ClsCommon.str_CardNumber.Length == 18) { txtmskcrdnum.Text = string.Concat(ClsCommon.str_cardNum1, " ", ClsCommon.str_cardNum2.Substring(0, 2), "XX", " ", "XXXX", " ", "XX", ClsCommon.str_cardNum4.Substring(2, 2), " ", ClsCommon.str_cardNum5); } if (ClsCommon.str_CardNumber.Length == 19) { txtmskcrdnum.Text = string.Concat(ClsCommon.str_cardNum1, " ", ClsCommon.str_cardNum2.Substring(0, 2), "XX", " ", "XXXX", " ", "XXX", ClsCommon.str_cardNum4.Substring(3, 1), " ", ClsCommon.str_cardNum5); } txtmskcrdnum.Text = ClsCommon.str_CardNumber.PadLeft(ClsCommon.str_CardNumber.Length, 'X').Substring(ClsCommon.str_CardNumber.Length - 4); 

对于多种长度,上述方法无用。

我想要一个显示前6个和后4个数字的方法,并用X屏蔽其他数字。最后一个字符串应该在每4个数字之间有一个空格。

这适用于任何卡号长度:

 var cardNumber = "3456123434561234"; var firstDigits = cardNumber.Substring(0, 6); var lastDigits = cardNumber.Substring(cardNumber.Length - 4, 4); var requiredMask = new String('X', cardNumber.Length - firstDigits.Length - lastDigits.Length); var maskedString = string.Concat(firstDigits, requiredMask, lastDigits); var maskedCardNumberWithSpaces = Regex.Replace(maskedString, ".{4}", "$0 "); 

我会做这样的事情(伪C# – 采取粗略的想法来构建)。

未经测试的代码……

 string MaskDigits(string input) { //take first 6 characters string firstPart = input.Substring(0, 6); //take last 4 characters int len = input.Length; string lastPart = input.Substring(len - 4, 4); //take the middle part (XXXXXXXXX) int middlePartLenght = input.Substring(6, len - 4).Count(); string middlePart = new String('X', 5); return firstPart + middlePart + lastPart; } 

试试这个。 简单直接。

 public static class StringExtensions { public static string Masked(this string source, int start, int count) { return source.Masked('x', start, count); } public static string Masked(this string source, char maskValue, int start, int count) { var firstPart = source.Substring(0, start); var lastPart = source.Substring(start + count); var middlePart = new string(maskValue, count); return firstPart + middlePart + lastPart; } } 

可能的实现(接受varios格式,例如数字可以分成组等):

 private static String MaskedNumber(String source) { StringBuilder sb = new StringBuilder(source); const int skipLeft = 6; const int skipRight = 4; int left = -1; for (int i = 0, c = 0; i < sb.Length; ++i) { if (Char.IsDigit(sb[i])) { c += 1; if (c > skipLeft) { left = i; break; } } } for (int i = sb.Length - 1, c = 0; i >= left; --i) if (Char.IsDigit(sb[i])) { c += 1; if (c > skipRight) sb[i] = 'X'; } return sb.ToString(); } // Tests // 3456-12XX-XXXX-1234 Console.Write(MaskedNumber("3456-1234-3456-1234")); // 3456123XXXXX1234 Console.Write(MaskedNumber("3456123434561234")); 

此实现只是屏蔽数字并保留格式。

一种方法:

 string masked = null; for (int i = 0; i < str_CardNumber.Length; i++) { masked += (i > 5 && i < str_CardNumber.Length - 4) ? 'X' : str_CardNumber[i]; if ((i + 1) % 4 == 0) masked += " "; } 

我确信有一种更清洁的方法可以做到这一点:

 int currentChar = 0; string maskable = "11111144441111"; string masked = maskable; int length = masked.Length; int startMaskPoint = 6; int endMaskPoint = length - 4 - startMaskPoint; masked = masked.Remove(startMaskPoint, endMaskPoint); int numRemoved = length - masked.Length; string Mask = ""; while (numRemoved != 0) { Mask = Mask + "#"; numRemoved--; } masked = masked.Insert(startMaskPoint, Mask); string returnableString = masked; while (length > 4) { returnableString = returnableString.Insert(currentChar + 4, " "); currentChar = currentChar + 5; length = length - 4; } 

如何使用Regex替换特定的匹配组:

  string cardNumber = "3456123434561234"; var pattern = "^(.{6})(.+)(.{4})$"; var maskedNumber = Regex.Replace(cardNumber, pattern, (match) => { return Regex.Replace(String.Format("{0}{1}{2}", match.Groups[1].Value, // the first 6 digits new String('X', match.Groups[2].Value.Length), // X times the 'X' char match.Groups[3].Value) /*the last 4 digits*/,".{4}", "$0 "); //finally add a separator every 4 char }); 

许多给定的解决方案多次解析输入。 下面我提出一个只解析输入一次的解决方案。 但是我没有C#的经验,所以函数是用Scheme编写的。

function分为两个:

(1)visit-first-6解析前六个字符并将它们连接到其余的计算中。 当visit-first-6解析了前六个字符时,它会调用visit-rest。

(2)访问 – rest利用了这样一个事实,即我们可以延迟一些计算,直到我们获得更多的知识。 在这种情况下,我们等待确定是否应该显示列表中的元素,直到我们知道剩下多少个字符。

 (define (mask xs) (letrec ([visit-first-6 (lambda (xs chars-parsed) (cond [(null? xs) ;; Shorter than 6 characters. '()] [(< chars-parsed 6) ;; Still parsing the first 6 characters (cons (car xs) (visit-first-6 (cdr xs) (1+ chars-parsed)))] [else ;; The first 6 characters have been parsed. (visit-rest xs (lambda (ys chars-left) ys))]))] [visit-rest (lambda (xs k) (if (null? xs) ;; End of input (k '() 0) ;; Parsing rest of the input (visit-rest (cdr xs) (lambda (rest chars-left) (if (< chars-left 4) ;; Show the last 4 characters (k (cons (car xs) rest) (1+ chars-left)) ;; Don't show the middle characters (k (cons "X" rest) (1+ chars-left)))))))]) (visit-first-6 xs 0))) 

在Petite Chez Scheme翻译中运行面具

 > (mask '(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)) (1 2 3 4 5 6 "X" "X" "X" "X" "X" "X" "X" "X" 15 16 17 18) > (mask '()) () > (mask '(1 2 3 4)) (1 2 3 4) > (mask '(1 2 3 4 5)) (1 2 3 4 5) > (mask '(1 2 3 4 5 6 7 8 9)) (1 2 3 4 5 6 7 8 9) > (mask '(1 2 3 4 5 6 7 8 9 10)) (1 2 3 4 5 6 7 8 9 10) > (mask '(1 2 3 4 5 6 7 8 9 10 11)) (1 2 3 4 5 6 "X" 8 9 10 11) 

NB。 我认为这是一个有趣的练习,我想我也可以分享它。 Yannick Meeus已经提供了一个易于理解的解决方案。 所以,这只适合感兴趣的人。

Linq保存了编码行,小代码片段。

用(*)char替换6以上,低于CardPan长度减去4

 var CardPan = "1234567890123456"; var maskedPan = CardPan.Aggregate(string.Empty, (value, next) => { if (value.Length >= 6 && value.Length < CardPan.Length - 4) { next = '*'; } return value + next; });