m
到n
个汉字组成的字符串,那么我可以使用以下代码:[single Chinese character regular expression]{m,n}
是否有一个单个中文字符的正则表达式,可以匹配任何存在的中文字符?
m
到n
个汉字组成的字符串,那么我可以使用以下代码:[single Chinese character regular expression]{m,n}
是否有一个单个中文字符的正则表达式,可以匹配任何存在的中文字符?
匹配中文(或CJK字符)的正则表达式是
\p{script=Han}
可以简写为
\p{Han}
这假设你的正则表达式编译器符合要求RL1.2从UTS#18 Unicode 正则表达式属性。 Perl和Java 7都符合该规范,但许多其他编译器则不符合。
\p{InCJK_UNIFIED_IDEOGRAPHS}{1,3}
\p{C}
字符块。 - Dr. Alex RE在C#中
new Regex(@"\p{IsCJKUnifiedIdeographs}")
这里是从Microsoft文档中找到的。
以下是维基百科提供的更多信息: CJK统一汉字
CJK统一汉字基本块(4E00–9FFF)包含20,976个基本汉字,范围为U+4E00至U+9FEF。该块不仅包括中文书写系统中使用的字符,还包括日本书写系统中使用的汉字和韩国正在逐渐减少使用的汉字。该块中的许多字符在所有三个书写系统中都有使用,而其他字符则只在其中一两个书写系统中使用。汉字也用于越南的Nôm文字(现已过时)。
有没有一个单个汉字的正则表达式,可以匹配任何已知的汉字?
建议
为了在支持Flex的词法分析器中匹配包含汉字和其他Unicode代码点的模式,您可以使用RE/flex词法分析器进行C++编程,它与Flex向后兼容。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 兼容性,因此您可以使用 yytext
、yyleng
、ECHO
等。如果没有使用 flex
选项,则 RE/flex 期望 Lexer 方法调用:text()
(或者对于 std::string
和 std::wstring
,str()
和 wstr()
)、size()
(或者对于宽字符长度,wsize()
)和 echo()
。我认为 RE/flex 的方法调用更加简洁,并包括宽字符操作。
背景
在普通的 Flex 中,我最终定义了丑陋的 UTF-8 模式来捕获 ASCII 字母和 UTF-8 编码的字母,以支持 Unicode 标识符 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代码点 (\p{L}
等)。该模式允许更多的Unicode代码点,以使该模式的大小可管理,因此在一些情况下允许UTF-8过长字符,但这些字符并不是有效的UTF-8,这种方式会导致一些准确性缺失和安全问题,请谨慎采用。建议使用 Unicode-capable 的扫描器生成器,例如RE/flex。
安全性
直接在Flex模式中使用UTF-8时存在以下几个问题:
在 Flex 中编码您自己的 UTF-8 模式以匹配任何 Unicode 字符可能容易出错。应该将模式限制为仅包含有效 Unicode 范围内的字符。Unicode 代码点覆盖范围从 U+0000 到 U+D7FF 和 U+E000 到 U+10FFFF。范围 U+D800 到 U+DFFF 保留用于 UTF-16 替代对,并且为无效的代码点。当使用工具将 Unicode 范围转换为 UTF-8 时,请确保排除无效的代码点。
为了捕获词法输入错误,您的词法分析器需要特殊的.
( 点) ,它匹配有效和无效的Unicode,包括UTF-8超出限定范围和无效字节序列,以便产生一个拒绝输入的错误消息。如果您使用点作为“捕获所有其他”以产生错误消息,但是您的点不匹配无效 Unicode,则您的词法分析器会挂起(“扫描器已卡住”)或者由 Flex 的“默认规则”在输出中回显垃圾字符。
您的扫描器应该识别输入中的UTF BOM (Unicode 字节顺序标记) 并切换到 UTF-8、UTF-16 (LE 或 BE) 或 UTF-32 (LE 或 BE)。
如您所指出的,例如[unicode characters]
这样的模式在 Flex 中根本不起作用,因为括号列表中的 UTF-8 字符是多字节字符,可以匹配每个单字节字符但无法匹配 UTF-8 字符。
请参考 RE/flex 用户指南中关于无效的 UTF 编码的说明。
\u4E00-\u9FFF
适用于:Python、现代JavaScript、Golang、Rust 但不适用于PHP。
如果您的语言不支持其他答案中的符号表示法,如{Han}
/{script=Han}
/{IsCJKUnifiedIdeographs}
,则此方法非常有用。
NB:这对应于CJK统一汉字,包括韩语、日语和越南语等其他语言。
[\u4E00-\u9FFF]
等同于[一-鿿]
。 - remcyclesInHan
,@Robert 只是添加了格式,使表达式呈现为等宽字体。 - Zoltán刚刚解决了一个类似的问题,
当你有太多的内容需要匹配时,最好使用 negated-set
并声明你不想匹配的内容,例如:
除数字外的所有内容:^[^0-9]*$
第二个 ^
将实现否定。
就像这样:
package main
import (
"fmt"
"regexp"
)
func main() {
compile, err := regexp.Compile("\\p{Han}") // match one any Chinese character
if err != nil {
return
}
str := compile.FindString("hello 世界")
fmt.Println(str) // output: 世
}
flex
(词法分析器)中使用了正则表达式功能。 - xiaohan2012