2010-12-02 7 views
20

Was ist eine gute Möglichkeit zu sagen, ob eine Zeichenfolge Text in einer Sprache von rechts nach links enthält.Wie erkennt man, ob ein Zeichen zu einer Sprache von Rechts nach Links gehört?

Ich habe diese question gefunden, die den folgenden Ansatz schlägt vor:

public bool IsArabic(string strCompare) 
{ 
    char[] chars = strCompare.ToCharArray(); 
    foreach (char ch in chars) 
    if (ch >= '\u0627' && ch <= '\u0649') return true; 
    return false; 
} 

Während dies für Arabisch arbeiten kann dies nicht andere RTL Sprachen scheint wie Hebräisch zu decken. Gibt es eine allgemeine Möglichkeit zu wissen, dass ein bestimmtes Zeichen zu einer RTL-Sprache gehört?

Antwort

20

Unicode-Zeichen haben unterschiedliche Eigenschaften. Diese Eigenschaften können nicht vom Codepunkt abgeleitet werden. Sie brauchen eine Tabelle, die Ihnen sagt, ob ein Charakter eine bestimmte Eigenschaft hat oder nicht.

Sie interessieren sich für Zeichen mit bidirektionaler Eigenschaft "R" oder "AL" (RandALCat).

Ein RandALCat-Zeichen ist ein Zeichen mit eindeutig rechts-nach-links-Direktionalität.

ist die komplette Liste als von Unicode 3.2 (von RFC 3454):

 
D. Bidirectional tables 

D.1 Characters with bidirectional property "R" or "AL" 

----- Start Table D.1 ----- 
05BE 
05C0 
05C3 
05D0-05EA 
05F0-05F4 
061B 
061F 
0621-063A 
0640-064A 
066D-066F 
0671-06D5 
06DD 
06E5-06E6 
06FA-06FE 
0700-070D 
0710 
0712-072C 
0780-07A5 
07B1 
200F 
FB1D 
FB1F-FB28 
FB2A-FB36 
FB38-FB3C 
FB3E 
FB40-FB41 
FB43-FB44 
FB46-FBB1 
FBD3-FD3D 
FD50-FD8F 
FD92-FDC7 
FDF0-FDFC 
FE70-FE74 
FE76-FEFC 
----- End Table D.1 ----- 

Hier einige Code, um die vollständige Liste als von Unicode 6.0 zu erhalten:

var url = "http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt"; 

var query = from record in new WebClient().DownloadString(url).Split('\n') 
      where !string.IsNullOrEmpty(record) 
      let properties = record.Split(';') 
      where properties[4] == "R" || properties[4] == "AL" 
      select int.Parse(properties[0], NumberStyles.AllowHexSpecifier); 

foreach (var codepoint in query) 
{ 
    Console.WriteLine(codepoint.ToString("X4")); 
} 

Beachten Sie, dass diese Werte sind Unicode-Codepunkte. Zeichenfolgen in C# /. NET sind UTF-16-codiert und müssen zuerst in Unicode-Codepunkte konvertiert werden (siehe Char.ConvertToUtf32). Hier ist eine Methode, die überprüft, ob eine Zeichenfolge enthält mindestens einen RandALCat Charakter:

static void IsAnyCharacterRightToLeft(string s) 
{ 
    for (var i = 0; i < s.Length; i += char.IsSurrogatePair(s, i) ? 2 : 1) 
    { 
     var codepoint = char.ConvertToUtf32(s, i); 
     if (IsRandALCat(codepoint)) 
     { 
      return true; 
     } 
    } 
    return false; 
} 
+0

Danke dafür !! Ich habe mich nur gefragt, was Sie von Brent denken? –

+1

@Patrick Kluge: Die Regex-Engine enthält anscheinend eine solche Tabelle mit Unicode-Eigenschaften. Aber ich sehe keine benannten Blöcke für alle RandALCat-Zeichen. Es hängt also von der Korrektheit ab, die Sie benötigen: Wenn Sie Arabisch und Hebräisch sowie einige andere Zeichen für gut genug halten, sollten Sie reguläre Ausdrücke verwenden. Wenn Sie ein vorhandenes RandALCat-Zeichen erkennen müssen, erstellen Sie Ihre eigene Tabelle und überprüfen Sie die Eingabezeichenfolge selbst, wie oben gezeigt. – dtb

+0

Ich frage mich, was Sie von dem ۞-Symbol, das von Software-Produkten wie Google Chrome und MS Word als rechts-nach-links behandelt wird, aber nicht als RandALCat in der Unicode-Spezifikation gekennzeichnet ist. –

16

Sie können versuchen, „named blocks“ in regular expressions verwenden. Einfach die Blöcke von rechts nach links auswählen und den Regex bilden. Zum Beispiel:

\p{IsArabic}|\p{IsHebrew} 

Wenn das regex true zurückgibt, dann gab es mindestens einen Hebräisch oder Arabisch Zeichen in der Zeichenfolge.

6

Alle "AL" oder "R" von Unicode 6.0 (von http://www.unicode.org/Public/6.0.0/ucd/UnicodeData.txt)

bool hasRandALCat = 0; 
if(c >= 0x5BE && c <= 0x10B7F) 
{ 
    if(c <= 0x85E) 
    { 
     if(c == 0x5BE)      hasRandALCat = 1; 
     else if(c == 0x5C0)     hasRandALCat = 1; 
     else if(c == 0x5C3)     hasRandALCat = 1; 
     else if(c == 0x5C6)     hasRandALCat = 1; 
     else if(0x5D0 <= c && c <= 0x5EA)  hasRandALCat = 1; 
     else if(0x5F0 <= c && c <= 0x5F4)  hasRandALCat = 1; 
     else if(c == 0x608)     hasRandALCat = 1; 
     else if(c == 0x60B)     hasRandALCat = 1; 
     else if(c == 0x60D)     hasRandALCat = 1; 
     else if(c == 0x61B)     hasRandALCat = 1; 
     else if(0x61E <= c && c <= 0x64A)  hasRandALCat = 1; 
     else if(0x66D <= c && c <= 0x66F)  hasRandALCat = 1; 
     else if(0x671 <= c && c <= 0x6D5)  hasRandALCat = 1; 
     else if(0x6E5 <= c && c <= 0x6E6)  hasRandALCat = 1; 
     else if(0x6EE <= c && c <= 0x6EF)  hasRandALCat = 1; 
     else if(0x6FA <= c && c <= 0x70D)  hasRandALCat = 1; 
     else if(c == 0x710)     hasRandALCat = 1; 
     else if(0x712 <= c && c <= 0x72F)  hasRandALCat = 1; 
     else if(0x74D <= c && c <= 0x7A5)  hasRandALCat = 1; 
     else if(c == 0x7B1)     hasRandALCat = 1; 
     else if(0x7C0 <= c && c <= 0x7EA)  hasRandALCat = 1; 
     else if(0x7F4 <= c && c <= 0x7F5)  hasRandALCat = 1; 
     else if(c == 0x7FA)     hasRandALCat = 1; 
     else if(0x800 <= c && c <= 0x815)  hasRandALCat = 1; 
     else if(c == 0x81A)     hasRandALCat = 1; 
     else if(c == 0x824)     hasRandALCat = 1; 
     else if(c == 0x828)     hasRandALCat = 1; 
     else if(0x830 <= c && c <= 0x83E)  hasRandALCat = 1; 
     else if(0x840 <= c && c <= 0x858)  hasRandALCat = 1; 
     else if(c == 0x85E)     hasRandALCat = 1; 
    } 
    else if(c == 0x200F)      hasRandALCat = 1; 
    else if(c >= 0xFB1D) 
    { 
     if(c == 0xFB1D)      hasRandALCat = 1; 
     else if(0xFB1F <= c && c <= 0xFB28) hasRandALCat = 1; 
     else if(0xFB2A <= c && c <= 0xFB36) hasRandALCat = 1; 
     else if(0xFB38 <= c && c <= 0xFB3C) hasRandALCat = 1; 
     else if(c == 0xFB3E)     hasRandALCat = 1; 
     else if(0xFB40 <= c && c <= 0xFB41) hasRandALCat = 1; 
     else if(0xFB43 <= c && c <= 0xFB44) hasRandALCat = 1; 
     else if(0xFB46 <= c && c <= 0xFBC1) hasRandALCat = 1; 
     else if(0xFBD3 <= c && c <= 0xFD3D) hasRandALCat = 1; 
     else if(0xFD50 <= c && c <= 0xFD8F) hasRandALCat = 1; 
     else if(0xFD92 <= c && c <= 0xFDC7) hasRandALCat = 1; 
     else if(0xFDF0 <= c && c <= 0xFDFC) hasRandALCat = 1; 
     else if(0xFE70 <= c && c <= 0xFE74) hasRandALCat = 1; 
     else if(0xFE76 <= c && c <= 0xFEFC) hasRandALCat = 1; 
     else if(0x10800 <= c && c <= 0x10805) hasRandALCat = 1; 
     else if(c == 0x10808)     hasRandALCat = 1; 
     else if(0x1080A <= c && c <= 0x10835) hasRandALCat = 1; 
     else if(0x10837 <= c && c <= 0x10838) hasRandALCat = 1; 
     else if(c == 0x1083C)     hasRandALCat = 1; 
     else if(0x1083F <= c && c <= 0x10855) hasRandALCat = 1; 
     else if(0x10857 <= c && c <= 0x1085F) hasRandALCat = 1; 
     else if(0x10900 <= c && c <= 0x1091B) hasRandALCat = 1; 
     else if(0x10920 <= c && c <= 0x10939) hasRandALCat = 1; 
     else if(c == 0x1093F)     hasRandALCat = 1; 
     else if(c == 0x10A00)     hasRandALCat = 1; 
     else if(0x10A10 <= c && c <= 0x10A13) hasRandALCat = 1; 
     else if(0x10A15 <= c && c <= 0x10A17) hasRandALCat = 1; 
     else if(0x10A19 <= c && c <= 0x10A33) hasRandALCat = 1; 
     else if(0x10A40 <= c && c <= 0x10A47) hasRandALCat = 1; 
     else if(0x10A50 <= c && c <= 0x10A58) hasRandALCat = 1; 
     else if(0x10A60 <= c && c <= 0x10A7F) hasRandALCat = 1; 
     else if(0x10B00 <= c && c <= 0x10B35) hasRandALCat = 1; 
     else if(0x10B40 <= c && c <= 0x10B55) hasRandALCat = 1; 
     else if(0x10B58 <= c && c <= 0x10B72) hasRandALCat = 1; 
     else if(0x10B78 <= c && c <= 0x10B7F) hasRandALCat = 1; 
    } 
} 
1

EDIT:

Dies ist, was ich jetzt verwenden, ist es die Vowelization Zeichen und alles auf Hebräisch beinhaltet und Arabisch:

[\u0591-\u07FF] 

ALTE ANTWORT:

Wenn Sie RTL Sprache in einem Satz zu erfassen brauchen, ist dieses vereinfachte RegEx wahrscheinlich genug sein:

[א-ת؀-ۿ] 

Wenn man etwas auf Hebräisch schreiben will, wird es haben eines dieser Zeichen zu verwenden, und die Fall ist ähnlich mit Arabisch.

Es enthält keine Vokalisierungszeichen. Wenn Sie also alle ganzen Wörter oder absolut alle RTL-Zeichen abfangen müssen, verwenden Sie besser eine der anderen Antworten. Vokalization Chars in Hebräisch sind sehr selten in Nicht-Poesie-Texten. Ich weiß nichts über arabische Texte.

Verwandte Themen