regex 如何处理组合字符沿着泰语字符串的\p{L}模式?

hk8txs48  于 2023-03-24  发布在  其他
关注(0)|答案(2)|浏览(181)

我需要检测与Unicode字符限制它的文字字母只(例如,没有符号,表情符号等,只是一些可以用在任何Unicode语言中的人名中的东西)。\p{L}类别似乎可以做到这一点,但它不能识别泰语字符串。我不会说泰语,所以我从ChatGPT得到了一些常见的泰语名字,它们在我的测试中都失败了。在RegExr上尝试了一下(参见测试选项卡),还写了一个简单的测试程序:

using System.Text.RegularExpressions;

Console.OutputEncoding = System.Text.Encoding.UTF8;

string pattern = @"^[\p{L}\s]+$";

string englishText = "Mary";
Console.Write($"{englishText}: ");
Console.WriteLine(Regex.IsMatch(englishText, pattern, RegexOptions.IgnoreCase).ToString()); // true

string germanText = "RöschenÜmit";
Console.Write($"{germanText}: ");
Console.WriteLine(Regex.IsMatch(germanText, pattern, RegexOptions.IgnoreCase).ToString()); // true

string thaiText = "อรุณรัตน์";
Console.Write($"{thaiText}: ");
Console.WriteLine(Regex.IsMatch(thaiText, pattern, RegexOptions.IgnoreCase).ToString()); // false

string japaneseText = "タクミたくみく";
Console.Write($"{japaneseText }: ");
Console.WriteLine(Regex.IsMatch(japaneseText, pattern, RegexOptions.IgnoreCase).ToString()); // true

我注意到,当我尝试测试泰语字符串中的每个字符时,它似乎将它们识别为有效的Unicode字母,但作为字符串,它失败了。为了确保没有隐藏任何字符,我检查了raw values,没有发现任何可疑之处。您知道这是怎么回事吗?
P.S.我知道测试中的一些字符来自不同的集合,名称可能包括空格,破折号等,但这不是重点。我只是想解决泰国字符串的问题。
注解:泰国字符串包含组合字符,我猜这会导致检测字母的问题,即使这些字母看起来像单个字母(即{0 e23,0xe 38}导致“”)。

2uluyalo

2uluyalo1#

如果我们打印出thaiText dump:

string thaiText = "อรุณรัตน์";

var report = string.Join(Environment.NewLine, thaiText
  .Select(c => $"{c} : \\u{(int)c:x4} : {char.GetUnicodeCategory(c)}"));

Console.WriteLine(report);

我们会找到行为不端的原因:OtherLetter s之间的NonSpacingMark s类别:

อ : \u0e2d : OtherLetter
ร : \u0e23 : OtherLetter
ุ : \u0e38 : NonSpacingMark <- doesn't match
ณ : \u0e13 : OtherLetter
ร : \u0e23 : OtherLetter
ั : \u0e31 : NonSpacingMark <- doesn't match
ต : \u0e15 : OtherLetter
น : \u0e19 : OtherLetter
์ : \u0e4c : NonSpacingMark <- doesn't match

从技术上讲,为了消除这些标记,我们可以使用 normalization

// The idea is to combine marks and letters into a letter which should match
thaiText = thaiText.Normalize(NormalizationForm.FormD);

但它在我的工作站上不起作用,原因是issue
因此,如果规范化在您的情况下也不起作用(或者您希望在道路的安全一侧),您可以尝试匹配泰语符号;要么只有泰国

string pattern = @"^[\p{IsThai}\s]+$";

或与所有其他字母(字母或泰语字母作为特例)混合:

string pattern = @"^[\p{L}\p{IsThai}\s]+$";

或允许 * 两个 * 字母(\p{L})和这些无间距标记(\p{Mn}):

string pattern = @"^[\p{L}\p{Mn}\s]+$";
c8ib6hqw

c8ib6hqw2#

这是因为有一些“标记”字符需要与字母分开匹配。一些语言使用这些字符,例如泰米尔语。这个正则表达式将匹配泰语字符串:

^[\p{L}\p{M}\s]+$

来自regular-expressions.info的有关\p{M}的信息:
\p{M}或\p{标记}:一种用来与另一个字符组合的字符(例如重音、元音变音、包围框等)。
此外,字符串与标记字符的比较:อรุณรัตน์和没有它们的字符串:อรณรตน-这个只与p{L}匹配。

相关问题