【问题标题】:Does POSIX regex.h provide unicode or basically non-ascii characters?POSIX regex.h 是否提供 unicode 或基本上非 ascii 字符?
【发布时间】:2012-01-04 13:37:10
【问题描述】:

您好,我正在使用标准正则表达式库(regcomp、regexec..)。但现在我应该根据需要为我的正则表达式代码添加 unicode 支持。

标准正则表达式库是否提供 unicode 或基本上非 ascii 字符?我在网上研究过,不认为​​。

我的项目是资源批评家,因此我不想为此使用大型库(ICU 和 Boost.Regex)。

任何帮助将不胜感激..

【问题讨论】:

标签: c++ c linux posix


【解决方案1】:

基本上,POSIX 正则表达式不支持 Unicode。您可以尝试在 Unicode 字符上使用它们,但可能会出现具有多种编码的字形问题以及 Unicode 感知库为您处理的其他此类问题。

来自标准,IEEE Std 1003.1-2008

匹配应基于用于编码字符的位模式,而不是基于字符的图形表示。这意味着如果一个字符集包含两个或多个图形符号的编码,或者如果搜索的字符串包含以多个代码集编码的文本,则不会尝试搜索编码符号的任何其他表示。如果需要,用户可以指定包含所需图形符号的所有变体的等价类。

也许libpcre 对你有用?它比 POSIX 正则表达式稍重,但我认为它比 ICU 或 Boost 轻。

【讨论】:

    【解决方案2】:

    看起来 POSIX 正则表达式在 UTF-8 语言环境下正常工作。我刚刚编写了一个简单的测试(见下文)并将其用于匹配带有西里尔字符的字符串与正则表达式"[[:alpha:]]"(例如)。一切正常。

    注意:您必须记住的主要内容 - 正则表达式函数与语言环境相关。所以你必须在它之前调用setlocale()

    #include <sys/types.h>
    #include <string.h>
    #include <regex.h>
    #include <stdio.h>
    #include <locale.h>
    
    int main(int argc, char** argv) {
      int ret;
      regex_t reg;
      regmatch_t matches[10];
    
      if (argc != 3) {
        fprintf(stderr, "Usage: %s regex string\n", argv[0]);
        return 1;
      }
    
      setlocale(LC_ALL, ""); /* Use system locale instead of default "C" */
    
      if ((ret = regcomp(&reg, argv[1], 0)) != 0) {
        char buf[256];
        regerror(ret, &reg, buf, sizeof(buf));
        fprintf(stderr, "regcomp() error (%d): %s\n", ret, buf);
        return 1;
      }
    
      if ((ret = regexec(&reg, argv[2], 10, matches, 0)) == 0) {
        int i;
        char buf[256];
        int size;
        for (i = 0; i < sizeof(matches) / sizeof(regmatch_t); i++) {
          if (matches[i].rm_so == -1) break;
          size = matches[i].rm_eo - matches[i].rm_so;
          if (size >= sizeof(buf)) {
            fprintf(stderr, "match (%d-%d) is too long (%d)\n",
                    matches[i].rm_so, matches[i].rm_eo, size);
            continue;
          }
          buf[size] = '\0';
          printf("%d: %d-%d: '%s'\n", i, matches[i].rm_so, matches[i].rm_eo,
                 strncpy(buf, argv[2] + matches[i].rm_so, size));
    
        }
      }
    
      return 0;
    }
    

    使用示例:

    $ locale
    LANG=ru_RU.UTF-8
    LC_CTYPE="ru_RU.UTF-8"
    LC_COLLATE="ru_RU.UTF-8"
    ... (skip)
    LC_ALL=
    $ ./reg '[[:alpha:]]' ' 359 фыва'
    0: 5-7: 'ф'
    $
    

    匹配结果的长度是两个字节,因为 UTF-8 中的西里尔字母占用太多。

    【讨论】:

    • 我想你误解了我的意思。我想这样做:./reg 'ç' 'çilek45'
    • 那么有什么问题呢?上面的代码打印出:0: 0-2: 'ç' 和你的参数。也就是说,它有效。
    • 有人知道如何使这个线程安全吗?看来uselocale对这些没有影响
    【解决方案3】:

    如果您的意思是“标准”,即来自 C++11 的 std::regex,那么您需要做的就是切换到 std::wregex(当然还有 std::wstring)。

    【讨论】:

    • 他们说的是 POSIX 标准规定的 regex.h 系统接口
    猜你喜欢
    • 2012-05-08
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 2015-04-10
    • 2015-07-01
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多