c++ - 如何使 std::regex 匹配 Utf8

标签 c++ regex utf-8

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

我已经在 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,将来可能会更改) .

不过,循环遍历各个字节会更有效:

  1. 如果前导位为 0,即其有符号值为 > -1 ,它是 1 字节字符表示。跳到下一个字节并重新开始。
  2. 否则,如果前导位为 11110,即其有符号值为 > -17 , n=4 .
  3. 否则,如果前导位为 1110,即其有符号值为 > -33 , n=3 .
  4. 否则,如果前导位为 110,即其有符号值为 > -65 , n=2 .
  5. (可选)检查下一个 n每个字节都以 10 开头,即对于每个字节,如果它有一个有符号值 < -63 ,这是无效的 UTF-8 编码。
  6. 您现在知道前 n 个字节构成了 unicode 独占字符。因此,如果下一个字符是“c”,即 == 99 ,你可以说它匹配 - return true .

关于c++ - 如何使 std::regex 匹配 Utf8,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50974253/

相关文章:

c++ - 将 PCRE 正则表达式中的任意数量的单词匹配到字符串中

c++ - 将数据从 const void *data 转换为 double

javascript - 使用 RegExp 获取最后一次出现的字符串

html - 正则表达式非捕获组正在捕获

c++ - C++ 中的 Unicode 问题,但不是 C

c++ - Vulkan 和 glfw - glfwVulkanSupported() 总是返回 false

c++ - 给定第一象限中的坐标列表,计算可以形成多少个单边平行于 x 轴的直角三角形

python - 快速解压大文本文件

Java处理request.getParameter中的特殊字符

eclipse - 如何在Eclipse中支持UTF-8编码