Извлечение значений в кавычках и без кавычек с помощью регулярных выражений

Я пытаюсь разобрать строку типа <tag>=<value> используя регулярные выражения, но столкнулись с некоторыми проблемами, добавив поддержку значений в кавычках. Идея состоит в том, что любые значения без кавычек должны быть обрезаны в начале / конце пробела так, чтобы [ Hello ] становится [Hello] (Просьба игнорировать квадратные скобки.)

Тем не менее, когда значение указано в кавычках, я хочу удалить что-либо, вплоть до двойных кавычек, но не дальше, поэтому [ " Hello World " ] станет [" Hello World "]

До сих пор я придумал следующий код с сопоставлением с образцом для этого (обратите внимание, что некоторые символы были экранированы или дважды экранированы, чтобы избежать их интерпретации как триграфов или других символов формата C).

void getTagVal( const std::string& tagVal )
{
boost::smatch what;
static const boost::regex pp("^\\s*([a-zA-Z0-9_-]+)\\s*=\\s*\"\?\?([%:\\a-zA-Z0-9 /\\._]+?)\"\?\?\\s*$");

if ( boost::regex_match( tagVal, what, pp ) )
{
const string tag = static_cast<const string&>( what[1] );
const string val = static_cast<const string&>( what[2] );

cout << "Tag = [" << tag << "] Val = [" << val << "]" << endl;
}
}

int main( int argc, char* argv[] )
{
getTagVal("Qs1= \" Hello World \" ");
getTagVal("Qs2=\" Hello World \" ");
getTagVal("Qs3= \" Hello World \"");
getTagVal("Qs4=\" Hello World \"");
getTagVal("Qs5=\"Hello World \"");
getTagVal("Qs6=\" Hello World\"");
getTagVal("Qs7=\"Hello World\"");

return 0;
}

Если убрать двойное побег, это будет выглядеть так:

  • ^ — Начало строки.
  • \s* — необязательное количество пробелов.
  • ([a-zA-Z0-9_-]+) — Один или несколько буквенно-цифровых символов или тире или подчеркивание. Это фиксируется как тег.
  • \s* — необязательное количество пробелов.
  • = — «равный» символ.
  • \s* — необязательное количество пробелов.
  • "?? — необязательная двойная кавычка (не жадная).
  • ([%:\a-zA-Z0-9 /\._]+?) — Один или несколько буквенно-цифровых символов или пробел, знак подчеркивания, процент, двоеточие, точка, прямая или обратная косая черта. Это фиксируется как значение (не жадное).
  • "?? — необязательная двойная кавычка (не жадная).
  • \s* — необязательное количество пробелов.
  • $ — Конец линии

Для примера звонки в main()Я бы ожидал получить:

Tag = [Qs1] Val = [ Hello World ]
Tag = [Qs2] Val = [ Hello World ]
Tag = [Qs3] Val = [ Hello World ]
Tag = [Qs4] Val = [ Hello World ]
Tag = [Qs5] Val = [Hello World ]
Tag = [Qs6] Val = [ Hello World]
Tag = [Qs7] Val = [Hello World]

но то, что я на самом деле получаю, это:

Tag = [Qs1] Val = [" Hello World ]
Tag = [Qs2] Val = [" Hello World ]
Tag = [Qs3] Val = [" Hello World ]
Tag = [Qs4] Val = [" Hello World ]
Tag = [Qs5] Val = ["Hello World ]
Tag = [Qs6] Val = [" Hello World]
Tag = [Qs7] Val = ["Hello World]

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

0

Решение

Я бы изменил часть, начиная с первой цитаты, на альтернативу:

"([^"]+)"|([%:\a-zA-Z0-9 /\._]+)\s*

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

1

Другие решения

Разобрался в чем проблема.

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

Итак, сказать, что я хочу \ чтобы быть в моем наборе символов в значении (что я делаю так же иронично, они используются в качестве escape-последовательностей в строке формата), тогда вы должны дважды экранировать их так

static const boost::regex pp("^\\s*([a-zA-Z0-9_-]+)\\s*=\\s*\"\?\?([%:\\a-zA-Z0-9 /\\._]+?)\"\?\?\\s*$");

будет выглядеть так:

static const boost::regex pp("^\\s*([a-zA-Z0-9_-]+)\\s*=\\s*\"\?\?([%:\\\\a-zA-Z0-9 /._]+?)\"\?\?\\s*$");

(то есть вам нужно сделать это \\\\)

0