2013-11-04 262 views
3

試圖想出一個'簡單'正則表達式來屏蔽看起來像可能包含帳號的文本位。正則表達式掩蓋包含數字的單詞

在普通的英語:

  • 含有一個數字(或這些單詞串)的單詞應該匹配
  • 離開最後4位數字完整
  • 替換匹配的字符串的所有以前的部分有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 

用正則表達式可能這樣的安排更換?

我想我的「M將需要一些貪婪和前瞻的功能,但我必須在這些領域毫無經驗

+0

我很抱歉,但我看不到問題?你所得到的錯誤結果是什麼? –

+1

@Sniffer我已經根據他的模式添加了實際結果。 –

+0

@TimS。 ... 謝謝! –

回答

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; 
} 
+0

一個簡短的評論,你說'if(!previousNum)previousNum = true;''你可以通過簡單地說'previousNum = true;'並且移除if語句來降低複雜度。它會減少圈複雜度爲1 –

+1

@joe_coolish你是完全和絕對正確的。我很快寫了代碼。 – varocarbas

+1

除此之外,解開正則表達式的+1! –

2

你有沒有試過這樣:

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

與更換

xxxx${m1}${m2} 

This產生

xxxx6789 
xxxx5678 
xxxx5678 
xxxx3333 
xxxx5678 test string 

您不會得到'a123b456'以匹配...直到'b'變成數字。 ;-)

+1

這將取代最後一個例子中的「這是一個」 –

+0

在我寫答案的時候,他的例子也刪除了這個。從那時起,需求改變了;-) – Dweeberly

+0

哈哈,真好! 「嘿,這是規格!」 –

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))); 
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#代碼抓取最後四個字符。

相關問題