使用正则表达式匹配utf-8编码中的任何中文字符

时间:2012-03-06 00:53:36

标签: regex unicode flex-lexer non-english

例如,我想匹配一个由mn个汉字组成的字符串,然后我可以使用:

[single Chinese character regular expression]{m,n}

是否存在单个汉字的正则表达式,可能是存在的任何汉字?

6 个答案:

答案 0 :(得分:26)

匹配中文(好吧,CJK)角色的正则表达式是

\p{script=Han}

可以简单地用于

\p{Han}

这假设您的正则表达式编译器符合requirement RL1.2 Properties from UTS#18 Unicode Regular Expressions。 Perl和Java 7都符合该规范,但许多其他规则都没有。

答案 1 :(得分:6)

在Java中,

\p{InCJK_UNIFIED_IDEOGRAPHS}{1,3}

答案 2 :(得分:2)

  

是否存在单个汉字的正则表达式,可能是存在的任何汉字?

<强>建议

要将模式与中文字符和其他Unicode代码点与Flex兼容的词法分析器匹配,您可以使用RE/flex lexical analyzer用于向后兼容Flex的C ++。 RE / flex支持Unicode,并与Bison一起构建词法分析器和解析器。

您可以在RE / flex规范中编写Unicode模式(和UTF-8正则表达式),例如:

%option flex unicode
%%
[肖晗]   { printf ("xiaohan/2\n"); }
%%

使用全局%option unicode启用Unicode。您还可以使用局部修饰符(?u:)将Unicode限制为单个模式(因此其他所有内容仍为ASCII / 8位,如Flex中所示):

%option flex
%%
(?u:[肖晗])   { printf ("xiaohan/2\n"); }
(?u:\p{Han})  { printf ("Han character %s\n", yytext); }
.             { printf ("8-bit character %d\n", yytext[0]); }
%%

选项flex支持Flex兼容性,因此您可以使用yytextyylengECHO等。如果没有flex选项,RE / flex期望Lexer方法调用:text()(或str()wstr() std::stringstd::wstring),{{ 1}}(或size()表示宽字符长度)和wsize()。 RE / flex方法调用是更清晰的恕我直言,并包括宽字符操作。

<强>背景

在普通的Flex中,我最终定义了丑陋的UTF-8模式,以便为需要支持Unicode标识符的编译器项目捕获ASCII字母和UTF-8编码字母echo()

id

digit [0-9] alpha ([a-zA-Z_\xA8\xAA\xAD\xAF\xB2\xB5\xB7\xB8\xB9\xBA\xBC\xBD\xBE]|[\xC0-\xFF][\x80-\xBF]*|\\u([0-9a-fA-F]{4})) id ({alpha})({alpha}|{digit})* 模式支持在标识符(alpha等)中使用的ASCII字母,下划线和Unicode代码点。该模式允许更多的Unicode代码点,而不是绝对必要的,以保持这种模式的大小可管理,因此它在一些缺乏准确性的情况下交易紧凑性,并且在某些无效UTF-8的情况下允许UTF-8 overlong characters。如果您正在考虑这种方法而不是对问题和安全问题保持警惕。请使用支持Unicode的扫描仪生成器,例如RE/flex

<强>安全

在Flex模式中直接使用UTF-8时,有几个问题:

  1. 在Flex中编码您自己的UTF-8模式以匹配任何Unicode字符可能容易出错。模式应仅限于有效Unicode范围内的字符。 Unicode代码点覆盖范围U + 0000到U + D7FF和U + E000到U + 10FFFF。范围U + D800到U + DFFF保留用于UTF-16代理对,并且是invalid code points。使用工具将Unicode范围转换为UTF-8时,请确保排除无效的代码点。

  2. 模式应拒绝overlong和其他invalid byte sequences。不应无声地接受无效的UTF-8。

  3. 要捕获词法分析器中的词汇输入错误,需要一个特殊的\p{L}(点)来匹配有效和无效的Unicode,包括UTF-8溢出和无效的字节序列,以便产生错误消息输入被拒绝。如果你使用dot作为&#34; catch-all-else&#34;要生成错误消息,但你的点与无效的Unicode不匹配,那么你的词法分析器将挂起(&#34;扫描仪被卡住&#34;)或者你的词法分析器会在输出上的ECHO垃圾字符由Flex&#34;默认规则&#34;

  4. 您的扫描仪应识别输入中的UTF BOM(Unicode字节顺序标记),以切换为UTF-8,UTF-16(LE或BE)或UTF-32(LE或BE)

  5. 正如您所指出的那样,.等模式根本不适用于Flex,因为括号列表中的UTF-8字符是多字节字符,每个单字节字符可以匹配但不能匹配UTF -8个字符。

  6. 另请参阅RE / flex用户指南中的invalid UTF encodings

答案 3 :(得分:1)

在C#中

new Regex(@"\p{IsCJKUnifiedIdeographs}")

这里是the Microsoft docs

这是来自维基百科的更多信息:CJK Unified Ideographs

名为CJK统一表意文字(4E00–9FFF)的基本块包含20,976个基本汉字,范围从U + 4E00到U + 9FEF。该块不仅包含中文书写系统中使用的字符,而且还包含日语书写系统中使用的汉字和汉字,而汉字在韩国逐渐减少。该块中的许多字符都在所有三个书写系统中使用,而其他字符仅在三个书写系统中的一两个中使用。越南的Nôm文字(现在已经过时)中也使用了汉字。

答案 4 :(得分:0)

刚刚解决了一个类似的问题,

当你有太多东西要匹配时,最好使用 negated-set 并声明你不想匹配的内容:

所有但不是数字:^[^0-9]*$

第二个 ^ 将实现否定

答案 5 :(得分:-2)

在Java 7及更高版本中,格式应为:&#34; \ p {IsHan}&#34;