Reputation: 46611
How can I take the value 123456789012345
or 1234567890123456
and turn it into:
************2345
and ************3456
The difference between the strings above is that one contains 15 digits and the other contains 16.
I have tried the following, but it does not keep the last 4 digits of the 15 digit number and now matter what the length of the string, be it 13, 14, 15, or 16, I want to mask all beginning digits with a *, but keep the last 4. Here is what I have tried:
String.Format("{0}{1}", "************", str.Substring(11, str.Length - 12))
Upvotes: 21
Views: 61424
Reputation: 4696
An extension method using C# 8's index and range:
public static string MaskStart(this string input, int showNumChars, char maskChar = '*') =>
input[^Math.Min(input.Length, showNumChars)..]
.PadLeft(input.Length, maskChar);
Upvotes: 0
Reputation: 528
How can I take the value 123456789012345 or 1234567890123456 and turn it into:
************2345 and ************3456
one more way to do this:
var result = new string('*',0,value.Length - 4) + new string(value.Skip(value.Length - 4).ToArray())
// or using string.Join
Upvotes: 0
Reputation: 1720
Mask from start and from end with sending char
public static string Maskwith(this string value, int fromStart, int fromEnd, char ch)
{
return (value?.Length >= fromStart + fromEnd) ?
string.Concat(Enumerable.Repeat(ch, fromStart)) + value.Substring(fromStart, value.Length - (fromStart + fromEnd)) + string.Concat(Enumerable.Repeat(ch, fromEnd))
: "";
} //Console.WriteLine("mytestmask".Maskwith(2,3,'*')); **testm***
show chars from start and from end by passing value and mask the middle
public static string MasktheMiddle(this string value, int visibleCharLength, char ch)
{
if (value?.Length <= (visibleCharLength * 2))
return string.Concat(Enumerable.Repeat(ch,value.Length));
else
return value.Substring(0, visibleCharLength) + string.Concat(Enumerable.Repeat(ch, value.Length - (visibleCharLength * 2))) + value.Substring(value.Length - visibleCharLength);
} //Console.WriteLine("mytestmask".MasktheMiddle(2,'*')); Result: my******sk
Upvotes: 0
Reputation: 11
// "123456789".MaskFront results in "****56789"
public static string MaskFront(this string str, int len, char c)
{
var strArray = str.ToCharArray();
for (var i = 0; i < len; i++)
{
if(i < strArray.Length)
{
strArray[i] = c;
}
else
{
break;
}
}
return string.Join("", strArray);
}
// "123456789".MaskBack results in "12345****"
public static string MaskBack(this string str, int len, char c)
{
var strArray = str.ToCharArray();
var tracker = strArray.Length - 1;
for (var i = 0; i < len; i++)
{
if (tracker > -1)
{
strArray[tracker] = c;
tracker--;
}
else
{
break;
}
}
return string.Join("", strArray);
}
Upvotes: 1
Reputation: 31
private 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 (****)
int middlePartLenght = len - (firstPart.Length + lastPart.Length);
string middlePart = new String('*', middlePartLenght);
return firstPart + middlePart + lastPart;
}
MaskDigits("1234567890123456");
// output : "123456******3456"
Upvotes: 3
Reputation: 11216
Something like this:
string s = "1234567890123"; // example
string result = s.Substring(s.Length - 4).PadLeft(s.Length, '*');
This will mask all but the last four characters of the string. It assumes that the source string is at least 4 characters long.
Upvotes: 46
Reputation: 18474
Regex with a match evaluator will do the job
string filterCC(string source) {
var x=new Regex(@"^\d+(?=\d{4}$)");
return x.Replace(source,match => new String('*',match.Value.Length));
}
This will match any number of digits followed by 4 digits and the end (it won't include the 4 digits in the replace). The replace function will replace the match with a string of * of equal length.
This has the additional benefit that you could use it as a validation algorthim too. Change the first + to {11,12} to make it match a total of 15 or 16 chars and then you can use x.IsMatch
to determine validity.
EDIT
Alternatively if you always want a 16 char result just use
return x.Replace(source,new String('*',12));
Upvotes: 2
Reputation: 302
Try this out:
static string Mask(string str)
{
if (str.Length <= 4) return str;
Regex rgx = new Regex(@"(.*?)(\d{4})$");
string result = String.Empty;
if (rgx.IsMatch(str))
{
for (int i = 0; i < rgx.Matches(str)[0].Groups[1].Length; i++)
result += "*";
result += rgx.Matches(str)[0].Groups[2];
return result;
}
return str;
}
Upvotes: 0
Reputation: 311566
Try this:
var maskSize = ccDigits.Length - 4;
var mask = new string('*', maskSize) + ccDigits.Substring(maskSize);
Upvotes: 6
Reputation: 1038940
using System;
class Program
{
static void Main()
{
var str = "1234567890123456";
if (str.Length > 4)
{
Console.WriteLine(
string.Concat(
"".PadLeft(12, '*'),
str.Substring(str.Length - 4)
)
);
}
else
{
Console.WriteLine(str);
}
}
}
Upvotes: 21
Reputation: 11990
A simple way
string s = "1234567890123"; // example
int l = s.Length;
s = s.Substring(l - 4);
string r = new string('*', l);
r = r + s;
Upvotes: -1
Reputation: 1057
static private String MaskInput(String input, int charactersToShowAtEnd)
{
if (input.Length < charactersToShowAtEnd)
{
charactersToShowAtEnd = input.Length;
}
String endCharacters = input.Substring(input.Length - charactersToShowAtEnd);
return String.Format(
"{0}{1}",
"".PadLeft(input.Length - charactersToShowAtEnd, '*'),
endCharacters
);
}
Adjust the function header as required, call with:
MaskInput("yourInputHere", 4);
Upvotes: 4
Reputation: 31857
Try the following:
private string MaskString(string s)
{
int NUM_ASTERISKS = 4;
if (s.Length < NUM_ASTERISKS) return s;
int asterisks = s.Length - NUM_ASTERISKS;
string result = new string('*', asterisks);
result += s.Substring(s.Length - NUM_ASTERISKS);
return result;
}
Upvotes: 2
Reputation: 17022
Easiest way: Create an extension method to extract the last four digits. Use that in your String.Format call.
For example:
public static string LastFour(this string value)
{
if (string.IsNullOrEmpty(value) || value.length < 4)
{
return "0000";
}
return value.Substring(value.Length - 4, 4)
}
In your code:
String.Format("{0}{1}", "************", str.LastFour());
In my opinion, this leads to more readable code, and it's reusable.
EDIT: Perhaps not the easiest way, but an alternative way that may produce more maintainable results. <shrug/>
Upvotes: 16
Reputation: 62524
LINQ:
char maskBy = '*';
string input = "123456789012345";
int count = input.Length <= 4 ? 0 : input.Length - 4;
string output = new string(input.Select((c, i) => i < count ? maskBy : c).ToArray());
Upvotes: 4