C++ 如何使std::regex与Utf8匹配

C++ 如何使std::regex与Utf8匹配,c++,regex,utf-8,C++,Regex,Utf 8,我想要一个像“.c”这样的模式,使用std::regex将“.”与任何后跟“c”的utf8匹配 我在微软C++和g++下尝试过。我得到相同的结果,每次“.”只匹配一个字节 下面是我的测试用例: #include <stdio.h> #include <iostream> #include <string> #include <regex> using namespace std; int main(int argc, char** argv)

我想要一个像“.c”这样的模式,使用std::regex将“.”与任何后跟“c”的utf8匹配

我在微软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;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main(int argc,字符**argv)
{
//生成一个包含3个UTF8字符的字符串
常量无符号字符p[]={a',0xC2,0x80',c',0};
要搜索的字符串((char*)p);
//要匹配c之前的UTF8字符吗
字符串模式(“.c”);
正则表达式re(模式);
std::smatch匹配;
bool r=std::regex_搜索(搜索、匹配、重搜索);
if(r)
{
//m.size()将是字节,我们预期为3
//预期为0xC2,0x80,'c'
字符串m=匹配[0];

cout一些正则表达式支持将匹配单个unicode字符的
\X
,该字符可能由许多字节组成,具体取决于编码方式。正则表达式引擎通常在引擎设计的编码中获取主题字符串的字节,因此您不必担心实际的编码g(无论是US-ASCII、UTF-8、UTF-16还是UTF-32)

另一个选项是
\uFFFF
,其中FFFF指的是unicode字符集中该索引处的unicode字符。使用该选项,您可以在字符类内创建范围匹配,即
[\u0000-\uFFFF]
。同样,这取决于regex风格支持什么。在
\x{…}中还有另一个
\u
的变体
除了必须在大括号内提供unicode字符索引外,它也做同样的事情,并且不需要填充,例如
\x{65}

编辑:该网站非常适合了解各种口味的regex

编辑2:要匹配任何Unicode独占字符,即不包括ASCII表中的字符/1字节字符,您可以尝试
“[\x{80}-\x{FFFFFFFF}”
即,值为128-4294967295的任何字符,从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独占字符。因此,如果下一个字符是“c”,即
    ==99
    ,您可以说它匹配-
    返回true

  • 使用宽字符和UTF32(如果您的编译器只支持UTF16)在标准C++中没有解决方案。所以基本上是代码> STD::ReGEX
    不支持UTF8,我确实有另一个ReXEP库,但是我期待标准的支持。标准中的Unicode支持是不存在的。也许我误解了你的意思。正在查找?当您说UTF-8字符时,您的意思是“任何有效的UTF-8字符”,即包括ASCII表(0-127)或者您的意思是ASCII表之外的字符?如果字符长度仅为1字节,是否不希望进行匹配?如果是,则需要基于非正则表达式的方法。UTF-8很容易解释。如果第一位为0,则长度为1字节。如果不是,则多字节字符中的单个字节,并且您知道前面的字符大于127。如果要确保编码正确,只需从前导字节开始计算字节。感谢更新。我希望点“.”匹配任何字符,包括单字节和多字节。然后我将结果字符串匹配解释为utf8。看起来
    std::regex
    不是这样工作的。这是一个遗憾。