c++ - 如何使 std::regex 匹配 Utf8
问题描述
我想要一个像“.c”这样的模式,匹配“。” 任何 utf8 后跟 'c' 使用 std::regex。
我在 Microsoft C++ 和 g++ 下尝试过。我得到相同的结果,每次“。” 只匹配一个字节。
这是我的测试用例:
#include <stdio.h>
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main(int argc, char** argv)
{
// make a string with 3 UTF8 characters
const unsigned char p[] = { 'a', 0xC2, 0x80, 'c', 0 };
string tobesearched((char*)p);
// want to match the UTF8 character before c
string pattern(".c");
regex re(pattern);
std::smatch match;
bool r = std::regex_search(tobesearched, match, re);
if (r)
{
// m.size() will be bytes, and we expect 3
// expect 0xC2, 0x80, 'c'
string m = match[0];
cout << "match length " << m.size() << endl;
// but we only get 2, we get the 0x80 and the 'c'.
// so it's matching on single bytes and not utf8
// code here is just to dump out the byte values.
for (int i = 0; i < m.size(); ++i)
{
int c = m[i] & 0xff;
printf("%02X ", c);
}
printf("\n");
}
else
cout << "not matched\n";
return 0;
}
我希望模式“.c”匹配我的tobesearched
字符串的 3 个字节,其中前两个是 2 个字节的 utf8 字符,后跟“c”。
解决方案
一些正则表达式支持\X
将匹配单个 unicode 字符,该字符可能由多个字节组成,具体取决于编码。正则表达式引擎在引擎设计使用的编码中获取主题字符串的字节是一种常见的做法,因此您不必担心实际编码(无论是 US-ASCII、UTF-8、 UTF-16 或 UTF-32)。
另一个选项是\uFFFF
FFFF 指的是 unicode 字符集中该索引处的 unicode 字符。这样,您可以在字符类中创建范围匹配,即[\u0000-\uFFFF]
. 同样,这取决于正则表达式支持的内容。还有另一种变体,\u
其中\x{...}
做同样的事情,除了必须在花括号内提供 unicode 字符索引,并且不需要填充,例如\x{65}
.
编辑:这个网站非常适合学习更多关于各种风格的正则表达式https://www.regular-expressions.info
编辑 2:要匹配任何 Unicode 专有字符,即不包括 ASCII 表中的字符/1 字节字符,您可以尝试"[\x{80}-\x{FFFFFFFF}]"
任何值为 128-4,294,967,295 的字符,即从 ASCII 范围之外的第一个字符到最后一个字符当前使用最多 4 字节表示的 unicode 字符集索引(最初为 6,将来可能会更改)。
但是,通过单个字节循环会更有效:
- 如果前导位为 0,即如果它的有符号值为
> -1
,则它是一个 1 字节的字符表示。跳到下一个字节并重新开始。 - 否则,如果前导位为 11110,即其有符号值为
> -17
,n=4
。 - 否则,如果前导位是 1110,即如果它的有符号值为
> -33
,n=3
。 - 否则,如果前导位为 110,即其有符号值为
> -65
,n=2
。 - 可选地,检查下一个
n
字节每个都以 10 开头,即对于每个字节,如果它有一个有符号值< -63
,则它是无效的 UTF-8 编码。 - 您现在知道前面的 n 个字节构成了一个 unicode 独占字符。所以,如果 NEXT 字符是 'c' ie
== 99
,你可以说它匹配 -return true
。
推荐阅读
- email - 当 Google 表格中的值发生变化时发送电子邮件
- html - 与父母相比,CSS 和 HTML 下拉列表的 z-index 错误
- powershell - 使用 PowerShell 模块使用 DynamicMembership 创建 Teams-room
- python - 使用 Python 时 Visual Studio 中的这些红色方块是什么?
- open-policy-agent - OPA - http.send 方法抛出间歇性 403
- c# - 如何从 Default.aspx 文件中的 DB 获取字符串?
- c# - 使用实体框架从两个表中绑定数据网格视图
- tsql - TSQL 动态查询成视图
- clojure - Clojure partition-by:将一些元素分组,其他元素保持原样
- python - 动态熊猫数据框过滤器不起作用