I am trying to replace 1234567890123456 with ************3456 with the following code:
Regex.Replace(xml,@"\b\d{13,16}\b", string.Concat(new String('*',12),a.Value.Substring(a.Value.Length - 4)));
Where a.Value is the number, but it just results in:
****************
Complete code:
//Check if value is the credit card
if(a.Value.Length >= 13 && a.Value.Length <= 16)
xml = Regex.Replace(xml,@"\b\d{12}(?=\d{4})\b", new String('*',12));
else //If value is not a credit card, replace it with ***
xml = Regex.Replace(xml,@"\b\d+\b", "***");
I replaced the first part of the if statement with:
Regex.Replace(xml, @"\b\d{13,16}\b", match =>
String.Concat(new String('*', match.Length - 4), match.Value.Substring(match.Length - 4)));
but I still get *** for the cardnum.
Here is the XML. Note the card number can be between 13 and 16 digits and I always want to keep the last 4.
<Details>
<CreditCard cardnum='1234567890123456'
ccv='123'
exp='0212'
cardType='1'
name='joe' />
</Details>
long numeric;
string xml = @"<Details>
<CreditCard cardnum='1234567890123456'
ccv='123'
exp='0212'
cardType='1'
name='joe' />
</Details>";
XElement element = XElement.Parse(xml);
IEnumerable<XElement> elementsWithPossibleCCNumbers =
element.Descendants()
.Where(d => d.Attributes()
.Where(a => a.Value.Length >= 13 && a.Value.Length <= 16)
.Where(a => long.TryParse(a.Value, out numeric))
.Count() == 1).Select(x=>x);
foreach(var x in elementsWithPossibleCCNumbers)
{
foreach(var a in x.Attributes())
{
//Check if the value is a number
if(long.TryParse(a.Value,out numeric))
{
//Check if value is the credit card
if(a.Value.Length >= 13 && a.Value.Length <= 16)
Regex.Replace(xml,@"\b\d{12}(?=\d{4}\b)", new String('*',12));
else //If value is not a credit card, replace it with ***
xml = Regex.Replace(xml,@"\b\d+\b", "***");
}
}
}
You can use lookahead to match the trailing 4 digits but preserve them:
Edit: This version is closer to your code. However, rather than relying on a pre-set
a.Value, it uses thematchvariable to allow you to apply your transformation on whatever was actually captured in your regex.The above code assumes that you want your redacted string to have the same length as the original, and preserve the last 4 digits.
If you want to redact the first 12 digits and preserve whatever remains (1–4 digits), use:
Edit: I think you already got it. But probably what you need to do is replace:
with:
Edit: I went through your now-complete code, and I realized that you don’t even need regex for what you’re trying to accomplish, since you’re replacing the attribute value in entirety. Here’s how I would adapt your code (with a number of changes):