У меня есть текстовый файл, который в настоящее время обрабатывается выражением regex
, и он работает хорошо. Формат файла хорошо определен, 2 числа, разделенные пробелами, а затем необязательный комментарий.Regex Соответствие необязательным номерам
Теперь у нас есть необходимость добавить дополнительное (но необязательное) третье число в этот файл, в результате чего формат, 2 или 3 номера разделяются пробелом с необязательным комментарием.
У меня есть объект regex
, который, по крайней мере, соответствует всем необходимым форматам линии, но мне не повезло с фактическим захватом третьего (дополнительного) номера, даже если он присутствует.
Код:
#include <iostream>
#include <regex>
#include <vector>
#include <string>
#include <cassert>
using namespace std;
bool regex_check(const std::string& in)
{
std::regex check{
"[[:space:]]*?" // eat leading spaces
"([[:digit:]]+)" // capture 1st number
"[[:space:]]*?" // each second set of spaces
"([[:digit:]]+)" // capture 2nd number
"[[:space:]]*?" // eat more spaces
"([[:digit:]]+|[[:space:]]*?)" // optionally, capture 3rd number
"!*?" // Anything after '!' is a comment
".*?" // eat rest of line
};
std::smatch match;
bool result = std::regex_match(in, match, check);
for(auto m : match)
{
std::cout << " [" << m << "]\n";
}
return result;
}
int main()
{
std::vector<std::string> to_check{
" 12 3",
" 1 2 ",
" 12 3 !comment",
" 1 2 !comment ",
"\t1\t1",
"\t 1\t 1\t !comment \t",
" 16653 2 1",
" 16654 2 1 ",
" 16654 2 1 ! comment",
"\t16654\t\t2\t 1\t ! comment\t\t",
};
for(auto s : to_check)
{
assert(regex_check(s));
}
return 0;
}
Это дает следующий результат:
[ 12 3]
[12]
[3]
[]
[ 1 2 ]
[1]
[2]
[]
[ 12 3 !comment]
[12]
[3]
[]
[ 1 2 !comment ]
[1]
[2]
[]
[ 1 1]
[1]
[1]
[]
[ 1 1 !comment ]
[1]
[1]
[]
[ 16653 2 1]
[16653]
[2]
[]
[ 16654 2 1 ]
[16654]
[2]
[]
[ 16654 2 1 ! comment]
[16654]
[2]
[]
[ 16654 2 1 ! comment ]
[16654]
[2]
[]
Как вы можете видеть, это соответствие всех ожидаемых входных форматов, но никогда не в состоянии фактически захватить 3-й номер , даже если он присутствует.
В настоящее время я тестирую это с помощью GCC 5.1.1, но этот фактический целевой компилятор будет GCC 4.8.2, используя boost::regex
вместо std::regex
.
Я бы лучше спал, если бы это было что-то вроде '\ s * (\ d +) \ s + (\ d +) (?: \ S + (\ d +))? \ S * (?:!. *)?' , Нежелательные квантификаторы заставляют меня нервничать. – melpomene
Я пробовал ваше регулярное выражение, и оно соответствовало строке «12». – melpomene
@melpomene да, спасибо, я ответил слишком быстро и не думал обо всех причудах оригинальной картины. –