Выполняет регулярное выражение POSIX.h предоставить символы unicode или в основном не ascii?

Привет я использую стандартную библиотеку регулярных выражений (regcomp, regexec..). Но теперь по требованию я должен добавить поддержку unicode к моим кодам для регулярных выражений.

предоставляет ли стандартная библиотека регулярных выражений символы unicode или в основном не ascii? Я исследовал в интернете, и думаю, что нет.

мой проект является ресурсным критиком, поэтому я не хочу использовать для него большие библиотеки (ICU и Boost.Регулярное выражение.)

любая помощь будет оценили..

3 ответов


похоже, что регулярное выражение POSIX работает правильно с локалем UTF-8. Я только что написал простой тест (см. ниже) и использовал его для сопоставления строки с кириллическими символами против regex "[[:alpha:]]" (например). И все работает просто отлично.

Примечание: главное, что вы должны помнить-функции regex связаны с языковым стандартом. Поэтому вы должны позвонить 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] = '';
      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 занимают так много.


в основном, POSIX regexes не знают Unicode. Вы можете попробовать использовать их на символах Unicode, но могут возникнуть проблемы с глифами с несколькими кодировками и другими такими проблемами, которые обрабатывают библиотеки Unicode.

из стандартного, IEEE Std 1003.1-2008:

сопоставление должно основываться на битовом шаблоне, используемом для кодирования символа, а не на графическом представлении символа. Это означает, что если набор символов содержит две или более кодировок для графического символа, или если строки поиска содержат текст, закодированный в более чем одном наборе кодов, не предпринимается попытка поиска любого другого представления закодированного символа. Если это необходимо, пользователь может указать классы эквивалентности, содержащие все варианты желаемого графического символа.

может быть libpcre будет работать для вас? Он немного тяжелее, чем POSIX regexes, но я бы подумал, что он легче, чем ICU или увеличить.


Если вы действительно имеете в виду" стандартный", то есть std::regex из C++11, то все, что вам нужно сделать, это перейти std::wregexstd::wstring конечно).