30

文字列に右から左への言語のテキストが含まれているかどうかを判断する良い方法は何ですか?

次のアプローチを示唆するこの質問を見つけました。

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

これはアラビア語では機能するかもしれませんが、ヘブライ語などの他の RTL 言語には対応していないようです。特定の文字が RTL 言語に属していることを知る一般的な方法はありますか?

4

5 に答える 5

26

Unicode 文字には、さまざまなプロパティが関連付けられています。これらのプロパティは、コード ポイントから派生させることはできません。キャラクターが特定のプロパティを持っているかどうかを示すテーブルが必要です。

双方向のプロパティ「R」または「AL」(RandALCat) を持つ文字に関心があります。

RandALCat 文字は、明確に右から左の方向性を持つ文字です。

Unicode 3.2 の完全なリストは次のとおりです ( RFC 3454から)。

D. 双方向テーブル

D.1 双方向プロパティ「R」または「AL」を持つ文字

----- 表 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
----- 表 D.1 の終了 -----

Unicode 6.0 の完全なリストを取得するためのコードを次に示します。

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

これらの値は Unicode コード ポイントであることに注意してください。C#/.NET の文字列は UTF-16 でエンコードされており、最初に Unicode コード ポイントに変換する必要があります ( Char.ConvertToUtf32を参照)。文字列に少なくとも 1 つの RandALCat 文字が含まれているかどうかを確認するメソッドを次に示します。

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;
}
于 2010-12-02T02:31:58.873 に答える
19

正規表現で「名前付きブロック」を使用してみることができます。右から左にあるブロックを選択して、正規表現を形成するだけです。例えば:

\p{IsArabic}|\p{IsHebrew}

その正規表現が true を返す場合、文字列に少なくとも 1 つのヘブライ文字またはアラビア文字が含まれています。

于 2010-12-02T02:37:21.610 に答える
9

Unicode 6.0 のすべての「AL」または「R」 ( 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;
    }
}
于 2012-08-01T16:15:31.743 に答える
3

編集:

これは私が今使っているもので、母音文字とヘブライ語とアラビア語のすべてが含まれています。

[\u0591-\u07FF]

古い答え:

文中の RTL 言語を検出する必要がある場合は、次の簡略化された正規表現で十分でしょう。

[א-ת؀-ۿ]

ヘブライ語で何かを書きたい場合は、これらの文字のいずれかを使用する必要があり、アラビア語の場合も同様です。

母音化文字は含まれていないため、すべての単語全体または絶対にすべての RTL 文字をキャッチする必要がある場合は、他の回答のいずれかを使用することをお勧めします。ヘブライ語の母音文字は、詩以外のテキストでは非常にまれです。アラビア語のテキストについてはわかりません。

于 2017-08-03T09:58:57.683 に答える
1

私の正規表現の実装では、\u、\x、または {} という名前のグループの言語を使用できませんでした。

そこで、 UnicodeData.txtにリストされているすべての「R」および「AL」(RandALCat) 双方向文字に基づいて、プログラムで独自のパターンを作成しました。

[־׀׃א-״؛-ي٭-ە‏ײַ-ﳝﶈ-ﷺﺂ-ﻼ]

これはかなり包括的である必要があり、これまでにアラビア語とヘブライ語のテキストでテストしました.

于 2019-10-30T17:18:11.327 に答える