屏蔽除字符串的前 6 位和后 4 位以外的所有数字(长度不同)
mask all digits except first 6 and last 4 digits of a string( length varies )
我有一个卡号作为字符串,例如:
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 个数字之间有一个 space。
我确定有更简洁的方法可以做到这一点:
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;
}
我会做这样的事情(伪 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;
}
这适用于任何卡号长度:
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}", "[=10=] ");
可能的实现(接受各种格式,例如数字可以分组等):
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 += " ";
}
如何使用正则表达式替换特定的匹配组:
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}", "[=10=] "); //finally add a separator every 4 char
});
许多给定的解决方案多次解析输入。
下面我提出了一个只解析一次输入的解决方案。
但是我没有C#经验,所以函数是用Scheme写的。
函数分为两个:
(1) visit-first-6 解析前六个字符并将它们连接到其余计算。
当 visit-first-6 解析完前六个字符后,调用 visit-rest。
(2) visit-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)
注意。我认为这是一个有趣的练习,我想我不妨分享一下。
Yannick Meeus 已经提供了一个易于理解的解决方案。
所以,这仅供感兴趣的人使用。
试试这个。简单明了。
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;
}
}
Linq 节省编码行,小代码片段。
用 (*) 字符替换 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;
});
str.substring(0, 5) +
str.substring(5, str.length() - 3)
.replaceAll("[\d]", "x") +
str.substring(str.length() - 3, str.length());
//这里是简单的做法
我认为这是最简单的形式。 PadLeft/PadRight 没有帮助我。我不知道,也没有在建议列表中找到,但是正确的函数不在 asp.net 核心 c# 代码中。
假设我有信用卡号(“2512920040512345”)并屏蔽除最后 4 位数字(“XXXXXXXXXXXX2345”)之外的所有数字。
//C# code will give you the desired output. Replace the string with your CreditCardno variable
new string('X', "2512920040512345".Length-4)+ "2512920040512345".Substring( "2512920040512345".Length-4, 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 个数字之间有一个 space。
我确定有更简洁的方法可以做到这一点:
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;
}
我会做这样的事情(伪 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;
}
这适用于任何卡号长度:
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}", "[=10=] ");
可能的实现(接受各种格式,例如数字可以分组等):
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 += " ";
}
如何使用正则表达式替换特定的匹配组:
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}", "[=10=] "); //finally add a separator every 4 char
});
许多给定的解决方案多次解析输入。 下面我提出了一个只解析一次输入的解决方案。 但是我没有C#经验,所以函数是用Scheme写的。
函数分为两个:
(1) visit-first-6 解析前六个字符并将它们连接到其余计算。 当 visit-first-6 解析完前六个字符后,调用 visit-rest。
(2) visit-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)
注意。我认为这是一个有趣的练习,我想我不妨分享一下。 Yannick Meeus 已经提供了一个易于理解的解决方案。 所以,这仅供感兴趣的人使用。
试试这个。简单明了。
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;
}
}
Linq 节省编码行,小代码片段。
用 (*) 字符替换 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;
});
str.substring(0, 5) +
str.substring(5, str.length() - 3)
.replaceAll("[\d]", "x") +
str.substring(str.length() - 3, str.length());
//这里是简单的做法
我认为这是最简单的形式。 PadLeft/PadRight 没有帮助我。我不知道,也没有在建议列表中找到,但是正确的函数不在 asp.net 核心 c# 代码中。
假设我有信用卡号(“2512920040512345”)并屏蔽除最后 4 位数字(“XXXXXXXXXXXX2345”)之外的所有数字。
//C# code will give you the desired output. Replace the string with your CreditCardno variable
new string('X', "2512920040512345".Length-4)+ "2512920040512345".Substring( "2512920040512345".Length-4, 4)