Токенизируйте строку, исключая разделители внутри кавычек - PullRequest
0 голосов
/ 24 октября 2011

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

Мне нужно извлечь все токены, кроме кавычек (для указанных), используя регулярное выражение boost.

Регулярное выражение, которое мне нужно использовать:

sregex pattern = sregex::compile("\"(?P<token>[^\"]*)\"|(?P<token>\\S+)");

Но я получаю ошибку:

именная отметка уже существует

Решение, опубликованное для C #, похоже, работает с дубликатом именованной метки, учитывая, что это выражение OR с другим.

Регулярное выражение для разделения на пробелы, кроме кавычек

Ответы [ 3 ]

3 голосов
/ 24 октября 2011

Я ответил на очень похожий вопрос здесь:

Как заставить мой сплит работать только на одной реальной строке и быть способным пропускать процитированные части строки?

Пример кода

  • использует Boost Spirit
  • поддерживает строки в кавычках, частично заключенные в кавычки, определенные пользователем разделители, экранированные кавычки
  • поддерживает множество (разнообразных) выходных контейнеров в общем
  • поддерживает модели концепции Range в качестве входных данных (включая char [], например)

Протестировано с относительно широким диапазоном версий компилятора и версий Boost.

https://gist.github.com/bcfbe2b5f071c7d153a0

0 голосов
/ 27 октября 2011

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

Вот код, который работал для меня:

    #include <boost/xpressive/xpressive.hpp>
    using namespace boost::xpressive;
...
    std::vector<std::string> tokens;
    std::string input = "here is a \"test string\"";
    sregex pattern = sregex::compile("\"(?P<quoted>[^\"]*)\"|(?P<unquoted>\\S+)");
    sregex_iterator cur( input.begin(), input.end(), pattern );
    sregex_iterator end;

    while(cur != end)
    {
      smatch const &what = *cur;
      if(what["quoted"].length() > 0)
      {
        tokens.push_back(what["quoted"]);
      }
      else
      {
        tokens.push_back(what["unquoted"]);
      }
      cur++;
    }
0 голосов
/ 24 октября 2011

Большинство разновидностей регулярных выражений не допускают повторного использования имен групп.Некоторые ароматы позволяют это, если все варианты использования находятся в одном и том же чередовании, но, очевидно, ваше использование не входит в их число.Однако, если вы используете достаточно свежую версию Boost, вы сможете использовать группу сброса ветви.Это выглядит так - (?|...|...|...) - и внутри каждой альтернативы нумерация групп сбрасывается туда, где она была до того, как была достигнута группа сброса ветви.Он также должен работать с именованными группами, но это не гарантировано.Я не в состоянии проверить это сам, поэтому попробуйте это:

"(?|\"(?P<token>[^\"]*)\"|(?P<token>\\S+))"

... и если это не сработает, попробуйте это с простыми старыми пронумерованными группами.

...