Есть некие фрагменты текста, которые, кроме общей обязательной части, могут содержать или не содержать строки с дополнительной информацией, то есть, к примеру, что-то такое:
заголовок
параметр 1: значение1
параметр 2: значение2
заголовок
параметр 2: значение2
параметр 3: значение3
Порядок строк постоянен, поэтому первое, что пришло в голову, это использовать конструкции вроде (?:параметр1: (\\d+))? - то есть строчка может присутствовать, и тогда нам требуется числовое значение, а может не присутствовать, тогда оно собственно и не нужно. Но такой подход не работает :-( Так нельзя?
Вот пример кода:
#include <iostream>
#include <string>
#include <pcrecpp.h>
using namespace std;
using namespace pcrecpp;
int main(int argc, char *argv[])
{
string text = "Это тест\n"
"первое значение: 10\n"
"второе значение: 20\n"
;
RE re("Это тест\n"
"(?:первое значение: (\\d+)\n)?"
"(?:второе значение: (\\d+)\n)?"
, RE_Options(PCRE_UTF8));
int v1 = -1, v2 = -1;
bool res = re.FullMatch(text, &v1, &v2);
cout << res << " " << v1 << " " << v2 << endl;
return 0;
}
Если код в таком виде, то re.FullMatch(text, &v1, &v2) возвращает true. Если в тексте закомментировать «первое значение: 10\n» или «второе значение: 20\n», то re.FullMatch(text, &v1, &v2) возвращает false (причём если закомментировать «второе значение: 20\n», то переменная v1 всё-таки меняет своё значение, но v2 - нет, ну а если закомментировать «первое значение: 10\n», то обе переменные сохраняют значение -1).
Но вот если не пытаться получить значения из скобок, то есть вместо re.FullMatch(text, &v1, &v2) написать re.FullMatch(text), то результат во всех трёх случаях - true. То есть получается, что само регулярное выражение срабатывает как нужно, дело лишь в том, что FullMatch может не хватать результатов чтобы записать в заданные переменные.
Похоже нельзя обработать такой текст одним регулярным выражением, нужно анализировать каждую строку отдельно? Или может всё-таки есть возможность не усложнять код и использовать одно регулярное выражение?