正则表达式掩盖包含数字的单词

时间:2013-11-04 19:26:43

标签: c# regex

试图想出一个'简单'的正则表达式来掩盖看起来可能包含帐号的文本。

用简单的英语:

  • 任何包含数字(或一系列此类单词)的单词都应匹配
  • 保留最后4位数字
  • 将匹配字符串的所有前一部分替换为四个X(xxxx)

到目前为止

我正在使用以下内容:

[\-0-9 ]+(?<m1>[\-0-9]{4})

替换为

xxxx${m1}

但是这会错过下面的最后几个样本

示例数据:

123456789
a123b456
a1234b5678
a1234 b5678
111 22 3333
this is a a1234 b5678 test string

实际结果

xxxx6789
a123b456
a1234b5678
a1234 b5678
xxxx3333
this is a a1234 b5678 test string

预期结果

xxxx6789
xxxxb456
xxxx5678
xxxx5678
xxxx3333
this is a xxxx5678 test string

这种安排是否可以用正则表达式替换?

我认为我需要一些贪婪和前瞻功能,但我在这些领域没有经验。

4 个答案:

答案 0 :(得分:3)

这适用于您的示例:

var result = Regex.Replace(
    input,
    @"(?<!\b\w*\d\w*)(?<m1>\s?\b\w*\d\w*)+",
    m => "xxxx" + m.Value.Substring(Math.Max(0, m.Value.Length - 4)));

如果您的值为111 2233 33,则会打印xxxx3 33。如果你希望它没有空格,你可以将lambda转换成一个多行语句,从该值中删除空格。

为了解释一下正则表达式,它有一个负面的后观,所以它确保它背后的单词中没有数字(在数字周围有可选的单词字符)。然后它得到了m1部分,它会查找带有数字的单词。在正则表达式模式解析其余部分之后,通过一些C#代码抓取最后四个字符。

答案 1 :(得分:2)

你试过这个:

.*(?<m1>[\d]{4})(?<m2>.*)

替换

xxxx${m1}${m2}

这会产生

xxxx6789
xxxx5678
xxxx5678
xxxx3333
xxxx5678 test string

你不会得到'a123b456'来匹配...直到'b'成为一个数字。 ; - )

答案 2 :(得分:2)

我不认为正则表达式是解决此问题的最佳方法,这就是我发布此答案的原因。对于如此复杂的情况,构建相应的正则表达式太困难了,更糟糕的是,它的清晰度和适应性远低于更长的代码方法。

这些行下方的代码提供了您所需的确切功能,它非常清晰,可以轻松扩展。

string input = "this is a a1234 b5678 test string";
string output = "";
string[] temp = input.Trim().Split(' ');
bool previousNum = false;
string tempOutput = "";
foreach (string word in temp)
{
    if (word.ToCharArray().Where(x => char.IsDigit(x)).Count() > 0)
    {
        previousNum = true;
        tempOutput = tempOutput + word;
    }
    else
    {
        if (previousNum)
        {
            if (tempOutput.Length >= 4) tempOutput = "xxxx" + tempOutput.Substring(tempOutput.Length - 4, 4);
            output = output + " " + tempOutput;
            previousNum = false;
        }
        output = output + " " + word;
    }
}
if (previousNum)
{
    if (tempOutput.Length >= 4) tempOutput = "xxxx" + tempOutput.Substring(tempOutput.Length - 4, 4);
    output = output + " " + tempOutput;
    previousNum = false;
}

答案 3 :(得分:1)

这是我非常快速的尝试:

(\s|^)([a-z]*\d+[a-z,0-9]+\s)+

这将选择所有这些测试用例。现在对于C#代码,您需要检查每个匹配项以查看匹配序列的开头或结尾是否有空格(例如,最后一个示例将在选定之前和之后具有空格)

这是执行替换的C#代码:

var redacted = Regex.Replace(record, @"(\s|^)([a-z]*\d+[a-z,0-9]+\s)+",
    match => "xxxx" /*new String("x",match.Value.Length - 4)*/ + 
    match.Value.Substring(Math.Max(0, match.Value.Length - 4)));