RegexOptions.CultureInvariant没有找到重音符号

时间:2016-11-25 08:46:36

标签: c# regex

我想创建一个忽略重音的正则表达式。

例如:

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等等。

3 个答案:

答案 0 :(得分:3)

使用以下方法:

    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并根据每个匹配的索引编辑原始字符串。

解释:(我正在使用“我是一个古老的élephant”字符串)

让我们将原始字符串的所有字符写入列表:

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

enter image description here

如您所见,char被定义为unicode char 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.

这意味着charé被“拆分”为e和重音字符。

要检查一下,让我们输出规范化字符串的字符:

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

enter image description here

如手表所示,é现已归一化为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字符串   分解,然后用它们替换序列   主要复合材料,如果可能的话。

答案 1 :(得分:1)

您正在指定Culture In 变体正则表达式。这意味着您的文化被忽略。所以你要么必须删除选项......

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

...或者如果您想独立于文化,请扩展您的模式:

string pattern = "[eé]lephant";

答案 2 :(得分: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