为什么此Regex.Replace无法正常工作
本文关键字:常工作 工作 Regex Replace 为什么 | 更新日期: 2023-09-27 18:22:14
我正试图用以下代码用************3456
替换1234567890123456
:
Regex.Replace(xml,@"'b'd{13,16}'b", string.Concat(new String('*',12),a.Value.Substring(a.Value.Length - 4)));
其中a.Value
是数字,但它只会产生:
****************
完整代码:
//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", "***");
我将if语句的第一部分替换为:
Regex.Replace(xml, @"'b'd{13,16}'b", match =>
String.Concat(new String('*', match.Length - 4), match.Value.Substring(match.Length - 4)));
但我仍然得到了卡号码的***
。
这是XML。请注意,卡号可以在13到16位之间,我总是想保留最后4位。
<Details>
<CreditCard cardnum='1234567890123456'
ccv='123'
exp='0212'
cardType='1'
name='joe' />
</Details>
长数字;
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", "***");
}
}
}
您可以使用前瞻来匹配后面的4位数字,但保留它们:
Regex.Replace(xml,@"'b'd{12}(?='d{4}'b)", new String('*',12))
编辑:此版本更接近您的代码。但是,它不依赖于预设的a.Value
,而是使用match
变量来允许您将转换应用于regex中实际捕获的内容。
Regex.Replace(xml, @"'b'd{13,16}'b", match =>
new String('*', match.Length - 4) +
match.Value.Substring(match.Length - 4));
上面的代码假设您希望经过编辑的字符串与原始字符串的长度相同,并保留最后4位数字。
如果您想编辑前12位数字并保留剩余的数字(1-4位),请使用:
Regex.Replace(xml, @"'b'd{13,16}'b", match =>
new String('*', 12) +
match.Value.Substring(12));
编辑:我想你已经得到了。但你可能需要做的是替换:
xml = Regex.Replace(xml, …
带有:
a.Value = Regex.Replace(a.Value, …
编辑:我仔细阅读了您现在完整的代码,我意识到您甚至不需要regex来完成您想要完成的任务,因为您要替换整个属性值。以下是我如何调整您的代码(进行了一些更改):
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()
.Select(a => a.Value)
.Any(v => v.Length >= 13 &&
v.Length <= 16 &&
v.All(Char.IsDigit)));
foreach (var x in elementsWithPossibleCCNumbers)
{
foreach (var a in x.Attributes())
{
//Check if the value is a number
if (a.Value.All(Char.IsDigit))
{
//Check if value is the credit card
if (a.Value.Length >= 13 && a.Value.Length <= 16)
a.Value = new String('*', a.Value.Length - 4) + a.Value.Substring(a.Value.Length - 4);
else //If value is not a credit card, replace it with ***
a.Value = "***";
}
}
}
xml = element.ToString();
您可以使用MatchEvaluator,在本例中,我使用了lambda。
[Test]
public void Test()
{
string xml = "foo 1234567890123456 bar";
Debug.WriteLine(Regex.Replace(xml, @"'b'd{9,12}(?='d{4}'b)", m => new string('*', m.Value.Length)));
}
foo ************3456 bar