Xaisoft
Xaisoft

Reputation: 46611

Mask out part first 12 characters of string with *?

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

Answers (15)

Chris Peacock
Chris Peacock

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

tanuk
tanuk

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

sonertbnc
sonertbnc

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

Donovan Huang
Donovan Huang

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

Mehmet Tastan
Mehmet Tastan

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

Chris Dunaway
Chris Dunaway

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

Bob Vale
Bob Vale

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

Mark Mintoff
Mark Mintoff

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

John Feminella
John Feminella

Reputation: 311566

Try this:

var maskSize = ccDigits.Length - 4;
var mask = new string('*', maskSize) + ccDigits.Substring(maskSize);

Upvotes: 6

Darin Dimitrov
Darin Dimitrov

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

Fabio
Fabio

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

anjunatl
anjunatl

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

Daniel Pe&#241;alba
Daniel Pe&#241;alba

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

Mike Hofer
Mike Hofer

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

sll
sll

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

Related Questions