От новичка до гуру: Курсы программирования на CyberDuff

BOOST Regex поведение глобального поиска

Мой вопрос о том, может ли механизм регулярных выражений boost выполнять "глобальный поиск".
Я пробовал, но не могу заставить его это сделать.

Класс match_results содержит базовый указатель строки, поэтому после увеличения
начальной позиции вручную и установки match_flag_type на match_not_bob | match_prev_avail,
я думал, что обработчик регулярных выражений Boost сможет узнать, что он находится в середине строка.

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

Ниже приведен пример кода/вывода с использованием регулярного выражения BOOST и эквивалентного сценария Perl.

Изменить. Чтобы уточнить, в приведенном ниже примере повышения итератор Start всегда рассматривается как граница. Кажется, что движок не учитывает текст слева от этой позиции при поиске соответствия.
По крайней мере, в этом случае.

22.07.2014 – Решение для глобального поиска

Публикация этого обновления в качестве решения. Это не обходной путь и не кладж.
Погуглив 'regex_iterator', я понял, что regex_iterator видит текст слева от текущей
позиции поиска. Причем, мне попадались все те же исходники. На одном сайте (как и на других)
было краткое простое объяснение того, как это работает, в котором говорилось, что он вызывает 'regex_search()'
при увеличении regex_iterator.

Итак, в недрах класса regex_iterator я увидел, что он действительно вызывал regex_search(), когда
итератор увеличивался ->Next().

Эта перегруженная версия regex_search() не была задокументирована и существует только в одном типе.
Она включает в конце параметр BIDI с именем base.

bool regex_search(BidiIterator first, BidiIterator last, 
                  match_results<BidiIterator, Allocator>& m, 
                  const basic_regex<charT, traits>& e, 
                  match_flag_type flags,
                  BidiIterator base)
{
   if(e.flags() & regex_constants::failbit)
      return false;

   re_detail::perl_matcher<BidiIterator, Allocator, traits> matcher(first, last, m, e, flags, base);
   return matcher.find();
}

Похоже, что база — это стена слева от начала BIDI, откуда начальный просмотр назад может использоваться для проверки условий.

Итак, я протестировал его, и он, похоже, сработал.
Суть в том, чтобы установить базовый BIDI в начале ввода, а начальный BIDI поставить где угодно после.
По сути, это похоже на настройку pos( ) переменная в Perl.

А чтобы эмулировать глобальное позиционное приращение при совпадении нулевой длины,
достаточно простого условного оператора:

Start = ( _M[0].length() == 0) ? _M[0].first + 1 : _M[0].second; (см. ниже)

Регулярное выражение BOOST 1.54 regex_search() с использованием «базового» BIDI
Примечание. В этом примере Start always = _M[0].second;
Регулярное выражение намеренно отличается от двух других примеров ( под ним), чтобы продемонстрировать на самом деле
текст от 'Base' до 'Start' учитывается каждый раз при сопоставлении этого регулярного выражения.

#typedef std::string::const_iterator SITR;

boost::regex Rx( "(?<=(.)).", regex_constants::perl );
regex_constants::match_flag_type Flags = match_default;

string str("0123456789");

SITR Start = str.begin();
SITR End   = str.end();
SITR Base  = Start;
boost::smatch _M;

while ( boost::regex_search( Start, End, _M, Rx, Flags, Base) )
{
    string str1(_M[1].first, _M[1].second );
    string str0(_M[0].first, _M[0].second );
    cout << str1 << str0 << endl;

    // This line implements the Perl global match flag m//g ->
    Start = ( _M[0].length() == 0) ? _M[0].first + 1 : _M[0].second;
}

output:
01
12
23
34
45
56
67
78
89

Перл 5.10

use strict;
use warnings;

my $str = "0123456789";
while ( $str =~ /(?<=(..))/g )
{
    print ("$1\n");
}

output:**
01
12
23
34
45
56
67
78
89

Регулярное выражение BOOST 1.54 regex_search() без «базы»

string str("0123456789");
std::string::const_iterator Start = str.begin();
std::string::const_iterator End = str.end();
boost::regex Rx("(?<=(..))", regex_constants::perl);
regex_constants::match_flag_type Flags = match_default;
boost::smatch _M;  

while ( boost::regex_search( Start, End, _M, Rx, Flags) )
{
    string str(_M[1].first, _M[1].second );
    cout << str << "\n";
    Flags |= regex_constants::match_prev_avail;
    Flags |= regex_constants::match_not_bob;
    Start = _M[0].second;
}

output:
01
23
45
67
89
15.07.2014

  • regex_iterator‹›::second должен содержать последнюю позицию совпадения в интервале [begin, end). Вы пытались вместо этого начать с M[0].first + 1? 15.07.2014
  • @ HomeroC.deAlmeida - Спасибо за ответ. Я знаю, что начальную позицию можно установить вручную. Регулярное выражение не привязано к какой-либо одной вещи. Таким образом, общее поведение должно исходить от двигателя. 15.07.2014

Ответы:


1

Обновлено в ответ на комментарии Live On Coliru :

#include <boost/regex.hpp>

int main()
{
    using namespace boost;

    std::string str("0123456789");
    std::string::const_iterator start = str.begin();
    std::string::const_iterator end = str.end();
    boost::regex re("(?<=(..))", regex_constants::perl);

    regex_constants::match_flag_type flags = match_default;
    boost::smatch match;  

    while (start<end && 
           boost::regex_search(start, end, match, re, flags))
    {
        std::cout << match[1] << "\n";

        start += 1; // NOTE

        //// some smartness that should work for most cases:
        // start = (match.length(0)? match[0] : match.prefix()).first + 1;

        flags |= regex_constants::match_prev_avail;
        flags |= regex_constants::match_not_bob;

        std::cout << "at '" << std::string(start,end) << "'\n";

    }
}

Отпечатки:

01  at '123456789'
12  at '23456789'
23  at '3456789'
34  at '456789'
45  at '56789'
56  at '6789'
67  at '789'
78  at '89'
89  at '9'
15.07.2014
  • Спасибо @sehe. Это хороший симулятор. К сожалению, его нельзя обобщить с помощью введенных пользователем регулярных выражений. Что-то вроде этого Start = (_M[0].length() == 0) ? _M[0].first + 1 : _M[0].second; прерывается с помощью регулярного выражения (?<=.). Даже (?=.) отправляет его в бесконечный цикл с использованием Start = _M[0].second; Я мог бы написать обходной путь в этом случае, но невозможность увидеть текст в местах ‹ Start делает его калекой. 16.07.2014
  • Ах. Теперь я понял истинную суть вашего вопроса. К сожалению, я думаю, что вы упускаете из виду более широкую картину: принятие пользовательского ввода в виде регулярных выражений в любом случае является огромной безопасностью. Вы захотите выполнить проверку или ограничить доступное подмножество конструкций регулярных выражений (здесь было бы неплохо что-то без просмотра вперед/назад) 16.07.2014
  • На самом деле это просто коммерческое программное обеспечение, встраивающее регулярное выражение boost в качестве одношаговой утилиты поиска/замены. Он полностью защищен с обработкой исключений. Я знаю этот двигатель как свои пять пальцев, это единственное, что меня зацепило. 16.07.2014
  • Ну что ж. Это просто одна вещь, которую вы ударили :) Я, вероятно, смогу создать какое-нибудь регулярное выражение, которое отправит ваш компьютер в кому - потенциально потеряв работу. Но, знаете, если это просто коммерческий софт, то это не важно, я полагаю. 16.07.2014
  • Обновить Я просмотрел ссылку на ваш профиль, и мне кажется, что вы понимаете, о чем я говорю. Ну тогда. Вы можете попробовать проявить фантазию и обнаружить совпадения нулевой ширины, такие как start = (match.length(0)? match[0] : match.prefix()).first + 1;. Но, честно говоря, единственное, что я вижу, работает в общем, это просто start += 1, но это может быть дорого для производительности в простых случаях. 16.07.2014
  • Я широко использую движок в других частях программы, и у меня есть несколько обходных путей для подвыражений, которые мне нужно использовать. Двигатель очень консервативен. Обычно, если существует потенциальный катастрофический потенциал возврата, он выдает исключение слишком сложного типа. Пока не делайте этого с введенным пользователем регулярным выражением, но всегда можно создать рабочий поток для выполнения поиска, а затем использовать интервальный таймер, который срабатывает через 10 секунд, что вызывает диалоговое окно с возможностью убить поток. Что-то такое. Насчет match.prefix() я знаю, что он есть, но с чего начать? 16.07.2014
  • Я отмечаю это как ответ. Насколько я знаю, regex_search не может выполнять глобальный поиск. Но я как-то узнал, что regex_iterator делает это. Спасибо за вашу помощь/предложение. 16.07.2014
  • Новые материалы

    Представляем Narwhal Technologies (Nrwl)
    6 декабря 2016 г. Маунтин-Вью, Калифорния С тех пор, как Виктор Савкин и я (Джефф Кросс) присоединились к команде Angular в Google на заре Angular 1, Angular продемонстрировал феноменальный..

    Путь AWS  — «Изучение машинного обучения — 10 начинающих ИИ и машинного обучения на AWS».
    Универсальный ресурсный центр для изучения искусственного интеллекта и машинного обучения. НОЛЬ или ГЕРОЙ, начните свое путешествие здесь. Получите решения и пройдите обучение у экспертов AWS...

    5 простых концепций Python, ставших сложными
    #заранее извините 1) Переменные x = 4 y = 5 Переменная в Python — это символическое представление объекта. После присвоения некоторого объекта переменной Python мы приобретаем..

    «Освоение вероятности: изучение совместной, предельной, условной вероятности и теоремы Байеса —…
    Виды вероятности: Совместная вероятность Предельная вероятность Условная вероятность Диаграмма Венна в вероятностях: В “Set Theory” мы создаем диаграмму Венна...

    Основы Spring: Bean-компоненты, контейнер и внедрение зависимостей
    Как лего может помочь нашему пониманию Когда мы начинаем использовать Spring, нам бросают много терминов, и может быть трудно понять, что они все означают. Итак, мы разберем основы и будем..

    Отслеживание состояния с течением времени с дифференцированием снимков
    Время от времени что-то происходит и революционизирует часть моего рабочего процесса разработки. Что-то более забавное вместо типичного утомительного и утомительного процесса разработки. В..

    Я предполагаю, что вы имеете в виду методы обработки категориальных данных.
    Я предполагаю, что вы имеете в виду методы обработки категориальных данных. Пожалуйста, проверьте мой пост Инструментарий специалиста по данным для кодирования категориальных переменных в..