c# - UnicodeCategory.Other正则表达式的字母范围

标签 c# javascript regex unicode

我需要将文本字段的长度限制为可变数量的字符。我说变量是因为它需要将CJK表意字符计为2个字符。例如,如果我将长度限制为10,那么我可以有10个拉丁字符,但只有5个表意文字,或者4个拉丁语和3个CJK表意文字(4 +(3 * 2))。

我通过使用以下命令在c#中实现了足够好的实现:

if (char.GetUnicodeCategory(str, i) == UnicodeCategory.OtherLetter)


关键是要在表单发布中进行检查,我真正想要的是在用户键入时检查JavaScript实现。我可以使用正则表达式来检查每个字符,但是我无法找出UnicodeCategory.OtherLetter使用哪个unicode块范围。

这个站点对于将正则表达式放在一起确实很有帮助,但是我只需要知道我要寻找的内容以匹配c#实现行为即可。

最佳答案

C#

首先,如果您的目标是仅将CJK表意字符计为2个字符,则您当前使用的C#代码不太正确。 Unicode通用类别OtherLetter或多或少地用于没有字母大小写概念的脚本。这意味着不仅CJK字符会匹配,阿拉伯语,希伯来语,高棉语,格鲁吉亚语等也会匹配。在Unicode数据中,CJK字符称为汉字。

不幸的是,我无法在.NET Framework中找到检查字符脚本的简单解决方案。但是,您可以使用.NET正则表达式来匹配Unicode Blocks。除了一般类别外,只需匹配必要的CJK blocks。不幸的是,尽管Unicode试图使块保持同质,但they makes no guarantees表示来自其他脚本的错误字符可能会以“错误”的块结尾。我想这对于CJK块来说不太可能。

另外,一个小问题是您可能要考虑使用System.Globalization.CharUnicodeData.GetUnicodeCategory(str, i)而不是char.GetUnicodeCategory(str, i)。出于向后兼容的原因,CharUnicodeData版本旨在与Unicode的当前版本保持最新,而其他版本则不是。

的JavaScript

不幸的是,JavaScript的Unicode支持不是那么好,尤其是在正则表达式方面。如果有一种方法可以获取JavaScript的常规类别,则实际上为already been asked。似乎没有,但是答案中提到了XRegExp plugin,除了脚本之外,它还可以检查字符的常规类别。

Mathias Bynens用great article详细说明了JavaScript当前在Unicode方面的缺点以及在即将发布的ECMAScript 6中预期的改进。他还提供了指向polyfills的链接以进行这些改进。

尽管ECMAScript 6为astral characters提供了更好的支持,但快速浏览一下current draft(2013年10月28日,修订版20)并没有迹象表明包括与Unicode General Categories,块或脚本匹配的支持。

星体角色

星体字符是在基本多语言平面(BMP,Plane 0)以外的平面中发现的那些字符,即值大于0xFFFF的字符。 C#和JavaScript都使用UTF-16作为其字符串编码。这意味着字符实际上是由2个代码单元形成的,而不是BMP中的1个。我的answer to a previous Unicode question进一步介绍了有关编码的细节,但足以说,这可能造成严重破坏。特别是,星形字符的字符串长度为2,而正则表达式引擎很难处理它们。

实际上,C#块和XRegExp解决方案都不能正确处理星体字符。许多罕见的CJK字符位于Supplementary Ideographic Plane(SIP,平面2)中。也就是说,“字符”是一个重载术语,已用于表示"code unit", "code point", and "user-perceived character"。对于这个答案,我一直在用它来表示代码点,但我不能说出您的意思,所以我能做的最好的就是让您知道星体字符的问题。

请注意,尽管尚未发布,但XRegExp的GitHub存储库指示即将发布的版本3中具有already implemented support for astral characters

手动匹配

考虑到所有困难,最好使用正则表达式手动匹配所有适当的代码点。当然,这样做的缺点是,当将新的CJK字符添加到标准中时,必须对其进行更新。 CJK表意文字的代码点可以在Unicode script data中找到,方法是搜索“ Han”脚本,然后采用Lo指示的范围(字母,其他)。在C#和JavaScript中应该(尽管未经测试)的相应正则表达式为:

[\u3400-\u4DB5\u4E00-\u9FCC\uF900-\uFA6D\uFA70-\uFAD9]|[\uD840-\uD868][\uDCOO-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|[\uD86A-\uD86C][\uDCOO-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDCOO-\uDC1D]|\uD87E[\uDC00-\uDE1D]


根据您的定义,代码点3005、3007、3021-3029、3038-303A,303B可能会或可能不会被视为表意文字。对于“字母,修饰符”和“数字,字母”,它们具有LmNl类别。

关于c# - UnicodeCategory.Other正则表达式的字母范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19661863/

相关文章:

c# - Any() 会在成功时停止吗?

c# - Funq 支持 ResolveAll 吗?

javascript - 如何从网页Javascript调用C#方法?

javascript - PHP获取提交按钮的值

java - 如何在 Java 中检测字符串是否包含西里尔字母?

c# - 如何将 xmlnamespace 添加到 xmldocument

javascript - “listener” 参数必须是函数类型。 MacOS 上的 Node.JS 9.3.0_1 有问题

javascript - 如何在Reactjs中动态创建页面

javascript - 替换字符串中的 HTML 实体,避免使用 <img> 标签

python - 使用selenium获取动态html表并使用beautifulsoup解析它