当我遇到正则表达式时,我转向了good'ol自定义解析方法.它并没有那么糟糕,因为文件内容可以非常巧妙地进行标记,并且可以使用非常简单的状态机在循环中解析标记.谁想要检查,还有的代码区间为,ifstream的迭代器和自定义的流标记者在#1我的其他问题这样一个片段在这里.这些技术大大降低了自定义解析器的复杂性.
我想在第一部分中将文件内容标记为两个捕获组,然后逐行标记.我喜欢半功能解决方案,但我想学习如何做得更好.也就是说,没有"额外处理"来弥补我对捕获组的缺乏知识.接下来是一些预赛,最后是一个更确切的问题(线路
const std::regex expression("([^:]+?)(^:|$)");
Run Code Online (Sandbox Code Playgroud)
...是我想要询问的与处理结果相关的那个).
基本上定义的文件如下:
definition_literal : value_literal
definition_literal : value_literal
definition_literal : value_literal
definition_literal : value_literal
HOW TO INTERPRET THE FOLLOWING SECTION OF ROWS
[DATA ROW 1]
[DATA ROW 2]
...
[DATA ROW n]
Run Code Online (Sandbox Code Playgroud)
其中每个数据行由一定数量的整数或由空格分隔的浮点数组成.每行具有与其他行一样多的数字(例如,每行可以具有四个整数).因此,"解释部分"基本上以一行的纯文本形式告诉这种格式.
我有一个几乎可以工作的解决方案,读取这样的文件:
int main()
{
std::ifstream file("xyz", std::ios_base::in);
if(file.good())
{
std::stringstream file_memory_buffer;
file_memory_buffer << file.rdbuf();
std::string str = file_memory_buffer.str();
file.close();
const std::regex expression("([^:]+?)(^:|$)");
std::smatch result;
const std::sregex_token_iterator end;
for(std::sregex_token_iterator i(str.begin(), str.end(), expression); i != end; ++i)
{
std::cout << (*i) << std::endl;
}
}
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
定义了正则表达式后expression
,它现在打印<value>
定义文件的各个部分,然后是解释部分,然后逐个打印数据行.如果我将正则表达式更改为
"([^:]+?)(:|$)"
Run Code Online (Sandbox Code Playgroud)
...它打印出所有标记为一组的行,几乎就像我想要的那样,但是如何将第一部分分成2组,其余部分逐行标记?
任何指针,代码,解释都是真正受欢迎的.谢谢.
正如汤姆克尔已经注意到的,但是还有一些额外的观点,这也是排练,或编码kata,如果你愿意,不写自定义解析器,但看看我是否可以 - 或者我们可以:-) - 完成这与正则表达式.我知道正则表达式不是最有效的方法,但这并不重要.
我希望有的是一个标题信息元组列表(大小为2的元组),然后是INTERPRET行(大小为1的元组),我可以用它来选择一个关于如何处理数据的函数行(大小为1的元组).
是的,"HOW TO INTERPRET"行包含在一组明确定义的字符串中,我可以从头开始逐行读取,沿途分割字符串,直到满足其中一条INTERPRET行.我知道,这个正则表达式解决方案不是最有效的方法,但更像编码kata让自己编写除客户解析器以外的其他内容(而且我最近一次用C++编写,所以这也是排练).
我已经设法通过更改迭代器类型来访问元组(在此问题的上下文中),就像这样
const std::sregex_iterator end;
for(std::sregex_iterator i(str.begin(), str.end(), expression); i != end; ++i)
{
std::cout << "0: " << (*i)[0] << std::endl;
std::cout << "1: " << (*i)[1] << std::endl;
std::cout << "2: " << (*i)[2] << std::endl;
std::cout << "***" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
虽然这仍然不像我想要的那样,但我正在尝试使用的正则表达式出现了问题.无论如何,这种新的发现,另一种迭代器,也有帮助.
我相信您正在尝试的是:
TEST(re) {
static const boost::regex re("^([^:]+) : ([^:]+)$");
std::string str = "a : b";
CHECK(boost::regex_match(str, re));
CHECK(!boost::regex_match("a:a : bbb", re));
CHECK(!boost::regex_match("aaa : b:b", re));
boost::smatch what;
CHECK(boost::regex_match(str, what, re, boost::match_extra));
CHECK_EQUAL(3, what.size());
CHECK_EQUAL(str, what[0]);
CHECK_EQUAL("a", what[1]);
CHECK_EQUAL("b", what[2]);
}
Run Code Online (Sandbox Code Playgroud)
但我不确定在这种情况下我会推荐正则表达式。我认为您会发现只需一次阅读一行,拆分:
,然后修剪空格就更容易管理。
我想如果你不能依赖下面的行作为哨兵,那么事情会更困难。通常我希望这样的格式从该行中显而易见,而不是标题的每一行的格式。
HOW TO INTERPRET THE FOLLOWING SECTION OF ROWS
Run Code Online (Sandbox Code Playgroud)