Подтвердить что ты не робот

Запуск регулярного выражения Ascii поверх символов, отличных от ASCII, с UTF-8

#include <boost/regex.hpp>

#include <string>
#include <vector>
#include <iostream>

int main(int argc, char* argv[]) {

    std::string text = argv[1];
    std::string patterns = argv[2];

    boost::regex regex = boost::regex(patterns);

    boost::smatch match;

    std::cout << boost::regex_search(text, match, regex) << std::endl;    
}

Если я запустил программу через вход hello¿ ¿ (содержащий символ не ASCII с кодировкой UTF-8), он возвращает 0, то есть не найден, но если я запустил его поверх ввода hel√ √ (снова содержащий не-ascii) он возвращает 1, то есть найден.

Мой вопрос: Каково ожидаемое поведение boost::regex (т.е. версия ascii) при выполнении над utf-символами?


Изменить: спасибо за все комментарии, меня все еще интересует, почему именно 1 выводится, так как текст и регулярное выражение содержат символы, отличные от ascii. Я предполагаю, что байты интерпретируются как ascii, и поэтому они соответствуют.

4b9b3361

Ответ 1

  • Использование регулярных выражений в строках ASCII - это использование "байтов" для поиска шаблона.
    Использование регулярных выражений в строках UTF-8 - это использование регулярных выражений в "многобайтовых" последовательностях, где последовательность представляет собой кодовую точку Unicode.

    Таким образом, регулярное выражение применяется к строке Unicode с кодировкой с байтом переменной байта на символ.

    Строки UTF-8 содержат многобайтовые последовательности с 1 по 4 байта, которые представляют собой символ "Юникод". В UTF-8 только 7-разрядные символы ASCII имеют 1 байтовый "широкий".

    Итак - с использованием механизма регулярных выражений ASCII в кодированной строке UTF-8, игнорирует многобайтовые последовательности в кодированной кодировке UTF-8 и вызывает сопоставление байт по байтам. Результаты этого использования механизма регулярного выражения ASCII в кодированной строке UTF-8 недействительны.

    Посмотрите http://utfcpp.sourceforge.net.

    Чтобы получить регулярные выражения, работающие с закодированными строками UTF-8, вам нужно...

    • Итераторы строк UTF-8 можно использовать с регулярными выражениями или
    • используйте std::codecvt_utf8 в комбинации временного назначения глобальной локали, чтобы заставить регулярное выражение работать, или
    • необходимо преобразовать кодированную строку UTF-8 в кодированную строку UTF-16, которая будет использоваться с движком регулярных выражений Unicode на основе std:: wstring.
  • Функция regex_search возвращает логическое значение и true в матче.
    В вашем случае шаблон регулярного выражения ASCII соответствует части кодированной строки UTF-8, которая не обрабатывается как строка ASCII - как вы предполагали!
    Если у вас есть текст на английском языке в кодировке UTF-8, то механизм регулярного выражения ASCII можно использовать безопасно. Оставляя ASCII 7-битный диапазон, делает результат работы механизма регулярного выражения ASCII ненадежным.

Ответ 2

Это ошибка, а не функция: Я попробовал ваш пример в лучшей системе (g++ 4.9.2 на Windows MinGW), и все происходит хорошо:

#include <iostream>
#include <string>
#include <regex>
int main()
{ std::string text ="hello¿"; // or "hello√"
  std::string patterns ="¿";  // or "√"
  std::regex regex = std::regex(patterns);
  std::smatch match;
  std::cout << std::regex_search(text, match, regex) << std::endl;
}

с выходом:

1