c++ 11正则表达式中UTF-8字符的范围
Range of UTF-8 Characters in C++11 Regex
这个问题是c++ 11正则表达式与UTF-8字符串工作吗?
#include <regex>
if (std::regex_match ("中", std::regex("中") )) // "u4e2d" also works
std::cout << "matchedn";
该程序是在Mac Mountain Lion上编译的clang++
与以下选项:
clang++ -std=c++0x -stdlib=libc++
上面的代码可以工作。这是一个用于匹配任何日本汉字或汉字的标准范围正则表达式"[一-龠々〆ヵヶ]"
。它在Javascript和Ruby中工作,但我似乎无法在c++ 11中工作,即使使用类似版本的[u4E00-u9fa0]
。下面的代码与字符串不匹配。
if (std::regex_match ("中", std::regex("[一-龠々〆ヵヶ]")))
std::cout << "range matchedn";
改变区域设置也没有帮助。什么好主意吗?
<标题>编辑所以我发现如果在末尾添加+
,所有范围都可以工作。在本例中,[一-龠々〆ヵヶ]+
,但如果您添加{1}
[一-龠々〆ヵヶ]{1}
,它不起作用。此外,它似乎超出了自己的界限。它不会匹配拉丁字符,但会匹配は
(即u306f
)和ぁ
(即u3041
)。它们都位于u4E00
nhahtdh还建议regex_search,它也可以在不添加+
的情况下工作,但它仍然遇到与上面相同的问题,通过在其范围之外拉值。我也玩了一些区域设置。Mark Ransom建议它将UTF-8字符串视为一组愚蠢的字节,我认为这可能是它正在做的事情。
进一步推动了UTF-8在某种程度上被混淆的理论,[a-z]{1}
和[a-z]+
匹配a
,但只有[一-龠々〆ヵヶ]+
匹配任何字符,而不是[一-龠々〆ヵヶ]{1}
。
用UTF-8编码,字符串"[一-龠々〆ヵヶ]"
等于这个字符串:"[xe4xb8x80-xe9xbexa0xe3x80x85xe3x80x86xe3x83xb5xe3x83xb6]"
。这不是你要找的机器人角色类。
您正在寻找的字符类是包含:
的字符类。- U+4E00 ~ U+9FA0范围内的任意字符;或
- 任意字符(,,,. )
指定的字符类包含:
- 任何"characters" xe4或xb8;或
- 任何"字符"在x80..xe9;或
- 任意"字符" xbe, xa0, xe3, x80, x85, xe3(再一次),x80(再一次),x86, xe3(再一次),x83, xb5, xe3(再一次),x83(再一次),x83(再一次),x83(再一次),xb6。
很乱,不是吗?你看到问题了吗?
这将不匹配"拉丁"字符(我假设你指的是像a-z这样的东西),因为在UTF-8中,这些字符都使用0x80以下的单个字节,并且这些字符都不在那个混乱的字符类中。
它也不会匹配"中"
,因为"中"
有三个"字符",而你的regex只匹配那个奇怪的长列表中的一个"字符"。试试assert(std::regex_match("中", std::regex("...")))
,你会看到。
如果你添加一个+
,它的工作,因为"中"
有三个"字符"在你的奇怪的长列表,现在你的正则表达式匹配一个或多个。
如果你添加{1}
,它将不匹配,因为我们又回到了三个"字符"对一个字符的匹配。
顺便说一下,"中"
匹配"中"
,因为我们以相同的顺序将三个"字符"与相同的三个"字符"进行匹配。
使用+
的正则表达式实际上会匹配一些不需要的东西,因为它不关心顺序。在UTF-8中可以从字节列表中生成的任何字符都将匹配。它将匹配"xe3x81x81"
(U+3041),它甚至将匹配无效的UTF-8输入,如"xe3xe3xe3xe3"
。
更大的问题是,您使用的regex库甚至不支持Unicode的1级支持,这是最低要求。它会改变字节,你宝贵的小正则表达式对此无能为力。
更大的问题是,你正在使用一组硬编码的字符来指定"任何日本汉字或汉字"。为什么不使用Unicode Script属性呢?
R"(p{Script=Han})"
哦,对了,这在c++ 11的正则表达式中不起作用。有那么一刻,我几乎忘记了它们在Unicode中比无用更糟糕。
那么你应该怎么做呢?
您可以将输入解码为std::u32string
,并使用char32_t
进行匹配。这不会给你带来这种混乱,但是当你指的是"一组共享某种属性的字符"时,你仍然会硬编码范围和异常。
我建议您忘记c++ 11正则表达式,并使用一些具有最低级别1 Unicode支持的正则表达式库,如ICU中的正则表达式库。
- 将超出范围的整数分配给有符号字符类型
- C++ - 使用基于范围的 for 循环将字符值分配给向量中的字符串不会分配值
- 将字符移出范围的危险
- 重命名两个目录中的文件名,如果它们之间的某些字符匹配 - 矢量下标超出范围
- 访问字符阵列中不可用的内存位置(超出范围值)
- 如何在 C++ 的字符串中打印从一个索引到另一个索引的字符范围
- 提升精神范围字符规则创建空字符
- 在最少的操作中实现字符串所有字符的相同频率。(所有字符的范围从'a'到"z")
- 输出在我的字符数组范围之外,同时使用 rand()
- C++ - "(常量字符*)"未在范围内声明?
- 如何将字符的范围从字符数组复制到矢量
- 提升正则和字符范围
- 循环直到整数输入在所需范围内无法处理非数字字符输入
- 如何检查字符是否在范围内
- 使用cctype库搜索函数,以查找某个范围内的数字字符数
- C++向量、常量字符*、变量范围和生存期
- 如何在c++中检查字符的unicode值的范围
- 将元素范围从字符数组提取到字符串中
- 在c++中指定一个ASCII小写字符范围
- 如何检查字符是否在给定的字符范围内