2016-11-25 100 views
0

我想創建一個忽略重音的正則表達式。RegexOptions.CultureInvariant找不到匹配的重音

例如:

string s = "I am an old élephant"; 
string pattern = "elephant"; 
bool result = new Regex(pattern, RegexOptions.CultureInvariant).IsMatch(s); 

我的文化當我測試的是:

System.Globalization.CultureInfo.CurrentCulture = Fr-fr 

所以我本來期望此代碼來找到一個匹配,但事實並非如此。

有沒有簡單的方法來獲得這個匹配?

我想做一個StringReplace重載方法,用大象等代替élèphânt。

+4

「我的文化,當我測試是」無關緊要,因爲你指定了'RegexOptions.CultureInvariant'。 – hvd

+1

@ A.D。看看http://stackoverflow.com/questions/249087/how-do-i-remove-diacritics-accents-from-a-string-in-net –

回答

4

使用下面的方法:

public string removeDiacritics(string str) 
    { 
     var sb = new StringBuilder(); 

     foreach (char c in str.Normalize(NormalizationForm.FormD)) 
     { 
      if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) 
      { 
       sb.Append(c); 
      } 
     } 
     return sb.ToString().Normalize(NormalizationForm.FormC); 
    } 

然後它

 string s = "I am an old élephant"; 
     string pattern = "elephant"; 
     bool result = new Regex(pattern, RegexOptions.IgnoreCase).IsMatch(removeDiacritics(s)); //true 

如果你必須替換一些東西,例如迭代(向後)通過matchcollection並根據每個匹配的索引編輯原始字符串。

釋解:(我使用的是「我是一個老大象」字符串)

讓我們寫的原始字符串的所有字符到一個列表:

foreach (char c in str) 
{ 
    chars1.Add(c); 
} 

enter image description here

由於你可以看到字符被定義爲Unicode字符233或00E9(見http://unicode-table.com/de/#00E9

標準化在這裏解釋 https://msdn.microsoft.com/en-us/library/system.text.normalizationform(v=vs.110).aspx

作爲機制的文檔說: 形式d:

Indicates that a Unicode string is normalized using full canonical decomposition. 

這意味着,炭E是「分裂」成e和口音炭。

要檢查,讓我們輸出的標準化字符串的字符:

List<char> chars2 = new List<char>(); 
foreach(char c in str.Normalize(NormalizationForm.FormD)) 
{ 
    chars2.Add(c); 
} 

enter image description here

如表所示,E是現在歸到2個字符(101(\ u0065)+ 769(\ u0301))

現在我們必須消除這些重音: 遍歷規範化字符串的所有字符,如果它是「NonSpacingMark」,則將其添加到StringBuilder。

MSDN: https://msdn.microsoft.com/en-us/library/system.globalization.unicodecategory(v=vs.110).aspx

NonSpacingMark

非間距字符表示基字符的修改。 由Unicode指定「Mn」(標誌,非間距)表示。該 值爲5

最後,以確保所有其他字符,即現在被定義爲我們的字符串2個或3個字符,越來越「轉換」成Unicode字符符號,我們必須正常化我們的新串返回到FormC。

MSDN: FormC:

表示一個Unicode字符串是使用完整規範 分解,隨後更換與其 初級複合序列,如果可能的話歸一化。

+0

這將工作。 Thx爲此:) –

+0

@ user1519979:也許你應該詳細說明它是如何工作的。我明白你在做什麼,但我不確定每個人都這樣做... – Sefe

+0

@Sefe done ..;) – user1519979

1

您在指定文化變異正則表達式。這意味着你的文化忽略。所以,你要麼必須刪除選項...

bool result = new Regex(pattern).IsMatch(s); 

...或者,如果你想成爲文化獨立,擴大你的模式:

string pattern = "[eé]lephant"; 
+0

默認情況下,沒有RegexOptions.CultureInvariant,它不起作用。 我的理解是,RegexOptions.CultureInvariant標籤會使它匹配,但我誤解了。 –

+0

string pattern =「[eé] lephant」;不是我正在尋找的,因爲我正在尋找一種通用方法來比較帶重音的字符串和沒有重音的字符串時的匹配。 我實際上正在嘗試創建一個StringReplace重載方法來替代élèphânt和大象等等。 –

+0

如果你想這樣做,使用'String.Equals'。你可以在那裏指定你的文化。正則表達式將幫助您完成匹配;對於文化敏感的搜索它不是很有用。你也應該更新你的問題來提供這種信息,否則你不會得到你想要的。 – Sefe

0

如果要使用正則表達式,可以使用\P{L}來指定給定的unicode字符是字母。

 string s = "I am an old ùûüÿàâçéèêëïîô"; 
     string pattern = @"(\p{L})"; 
     var regex = new Regex(pattern); 
     var result = regex.Replace(s, @"$1"); 
     Console.WriteLine(result);//I am an old uuuyaaceeeeiio