2016-11-25 3 views
0

Ich möchte eine Regex erstellen, die Akzent ignoriert.RegexOptions.CultureInvariant nicht finden Übereinstimmungen für Akzente

Zum Beispiel:

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

Meine Kultur, wenn ich testen:

System.Globalization.CultureInfo.CurrentCulture = Fr-fr 

So würde ich diesen Code erwartet eine Übereinstimmung zu finden, aber es funktioniert nicht.

Gibt es einen einfachen Weg, um eine Übereinstimmung dafür zu bekommen?

Ich versuche, eine StringReplace-Überladungsmethode zu machen, die élèphânt durch Elefanten ersetzen würde und so weiter.

+4

"Meine Kultur beim Testen ist" irrelevant, da Sie 'RegexOptions.CultureInvariant' angegeben haben. – hvd

+1

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

Antwort

4

Verwendung folgender Methode:

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); 
    } 

Dann funktioniert es

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

Wenn Sie müssen etwas ersetzen, z. Iteriere (rückwärts) durch die Matchcollection und bearbeite deine ursprüngliche Zeichenkette abhängig von den Indizes jeder Übereinstimmung.

Explaination: (i bin mit der "Ich bin ein alter Elefant" string)

Lassen Sie uns alle Zeichen der ursprünglichen Zeichenfolge in eine Liste schreiben:

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

enter image description here

Wie Sie können sehen, das Char ist definiert als Unicode Char 233 oder 00E9 (siehe http://unicode-table.com/de/#00E9)

Die Normalisierung wird hier erklärt https://msdn.microsoft.com/en-us/library/system.text.normalizationform(v=vs.110).aspx

Wie die Dokumention sagt: Form D:

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

Das bedeutet, dass das Zeichen é wird in eine E und einem Akzente char "aufgeteilt".

Um das zu überprüfen, lassen Sie sie gibt die Zeichen des normalisierten string:

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

enter image description here

Wie in der Uhr zu sehen ist, wird das é nun in 2 Zeichen normalisiert (101 (\ u0065) + 769 (\ u0301))

Jetzt müssen wir diese Akzente beseitigen: Durch alle Zeichen der normalisierten Zeichenkette Iterieren und wenn es eine "NonSpacingMark" ist, fügen Sie sie zum StringBuilder hinzu.

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

NonSpacingMark

Ohne Zwischenraum Charakter, die Modifikationen eines Basiszeichen angibt. Bezeichnet mit der Unicode-Bezeichnung "Mn" (Marke, Nonspacing). Der Wert ist 5.

Schließlich, um sicherzustellen, dass alle anderen Zeichen, die jetzt als 2 oder 3 Zeichen in unserem String definiert sind, werden „umgewandelt“ in das Unicode-Zeichen Symbol bekommen, müssen wir unsere neuen normalisieren String zurück zum FormC.

MSDN: FormC:

Zeigt an, dass eine Unicode-Zeichenfolge normiert volle kanonische Zersetzung verwendet wird, gefolgt von der Ersetzung von Sequenzen mit ihrer primären Komposite, wenn möglich.

+0

Das wird funktionieren. Thx dafür :) –

+0

@ user1519979: Vielleicht solltest du ein wenig ausarbeiten, wie es funktioniert. Ich verstehe, was Sie tun, aber ich bin mir nicht sicher, ob jeder ... – Sefe

+0

@Sefe getan ..;) – user1519979

1

Sie geben eine Kultur In Variante Regex. Das heißt, Ihre Kultur ist ignoriert. Also entweder Sie haben die Möglichkeit, entfernen ...

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

... oder wenn Sie Kultur unabhängig sein wollen, erweitern Sie Ihr Muster:

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

Standard, ohne RegexOptions.CultureInvariant, funktioniert es nicht. Mein Verständnis war, dass das RegexOptions.CultureInvariant-Tag es übereinstimmen würde, aber ich missverstanden. –

+0

string pattern = "[eé] lephant"; ist nicht das, wonach ich suche, da ich nach einer generischen Methode suche, um Übereinstimmungen zu finden, wenn ich eine Zeichenkette mit Akzent mit einer Zeichenkette ohne Akzente vergleiche. Ich versuche tatsächlich, eine StringReplace-Überladungsmethode zu machen, die élèphânt durch Elefanten ersetzen würde und so weiter. –

+0

10 Wenn Sie das tun möchten, verwenden Sie 'String.Equals'. Sie können dort Ihre Kultur angeben. Regex wird Ihnen mit genauen Übereinstimmungen helfen; Für kultursensitive Suchen ist es nicht sehr nützlich. Sie sollten auch Ihre Frage aktualisieren, um diese Art von Informationen bereitzustellen, sonst erhalten Sie nicht, was Sie wollen. – Sefe

0

Wenn Sie Regulärer Ausdruck verwenden möchten, können Sie \P{L} verwenden, um anzugeben, dass ein gegebener Unicode-Zeichen ein Buchstabe ist.

 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 
Verwandte Themen