C++ Boost regex以捕获所有重复的模式
我有一个包含以下内容的简单文本文件:C++ Boost regex以捕获所有重复的模式,c++,regex,boost,C++,Regex,Boost,我有一个包含以下内容的简单文本文件: VALUE "foo" ANOTHERVALUE "bar" YETANOTHERVALUE "barbar" 第1列中的值是已知的 我想捕获第1列和第2列中的所有内容 我的解决方案涉及手动将第1列(已知)的所有可能值写入regex字符串,但显然这不是理想的做法,因为我基本上是重复代码,这不允许灵活排序: const char* re = "^[[:space:]]*" "(VALUE)[[:space:]]*\"(.*)\"[[:sp
VALUE "foo"
ANOTHERVALUE "bar"
YETANOTHERVALUE "barbar"
第1列中的值是已知的
我想捕获第1列和第2列中的所有内容
我的解决方案涉及手动将第1列(已知)的所有可能值写入regex字符串,但显然这不是理想的做法,因为我基本上是重复代码,这不允许灵活排序:
const char* re =
"^[[:space:]]*"
"(VALUE)[[:space:]]*\"(.*)\"[[:space:]]*"
"(ANOTHERVALUE)[[:space:]]*\"(.*)\"[[:space:]]*"
"(YETANOTHERVALUE)[[:space:]]*\"(.*)\"[[:space:]]*";
我在这里引用评论员Igor Tandetnik的话,因为他在评论中几乎给出了完整的答案:
正则表达式捕获的子字符串数量与所捕获的子字符串数量完全相同 表达式[…]中的左括号 解决这个问题的正确方法是编写一个与 单对,[…] 注:
相当于\s
[:space:]
用于在字符串中第二个*?
而不是最后一个“
之后停止搜索”
#包括
#包括
#包括
注:
- 我使用raw使代码更干净
我在这里引用评论员伊戈尔·坦德尼克的话,因为他在评论中几乎给出了完整的答案:
正则表达式捕获的子字符串数量与所捕获的子字符串数量完全相同
表达式[…]中的左括号
解决这个问题的正确方法是编写一个与
单对,[…]
注:
\s
相当于[:space:]
*?
用于在字符串中第二个“
而不是最后一个”
之后停止搜索
并重复应用它,例如通过std::regex_迭代器
助推当量为
#包括
#包括
#包括
注:
- 我使用raw使代码更干净
我会在这里使用一个小型Spirit解析器:
阅读地图
#include <boost/fusion/adapted/std_pair.hpp> // reading maps
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <iostream>
#include <fstream>
#include <map>
auto read_config_map(std::istream& stream) {
std::map<std::string, std::string> settings;
boost::spirit::istream_iterator f(stream >> std::noskipws), l;
using namespace boost::spirit::x3;
auto key_ = lexeme [ +upper ];
auto value_ = lexeme [ '"' >> *~char_('"') >> '"' ];
if (!phrase_parse(f, l, -(key_ >> value_) % eol >> eoi, blank, settings))
throw std::invalid_argument("cannot parse config map");
return settings;
}
auto read_config_map(std::string const& fname) {
std::ifstream stream(fname);
return read_config_map(stream);
}
int main() {
for (auto&& entry : read_config_map(std::cin))
std::cout << "Key:'" << entry.first << "' Value:'" << entry.second << "'\n";
}
我会在这里使用一个小的Spirit解析器:
阅读地图
#include <boost/fusion/adapted/std_pair.hpp> // reading maps
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <iostream>
#include <fstream>
#include <map>
auto read_config_map(std::istream& stream) {
std::map<std::string, std::string> settings;
boost::spirit::istream_iterator f(stream >> std::noskipws), l;
using namespace boost::spirit::x3;
auto key_ = lexeme [ +upper ];
auto value_ = lexeme [ '"' >> *~char_('"') >> '"' ];
if (!phrase_parse(f, l, -(key_ >> value_) % eol >> eoi, blank, settings))
throw std::invalid_argument("cannot parse config map");
return settings;
}
auto read_config_map(std::string const& fname) {
std::ifstream stream(fname);
return read_config_map(stream);
}
int main() {
for (auto&& entry : read_config_map(std::cin))
std::cout << "Key:'" << entry.first << "' Value:'" << entry.second << "'\n";
}
正则表达式捕获的子字符串的数量与表达式中左括号的数量完全相同(大致上,非捕获组有一种语法,因此捕获的数量可能比括号少,但不能多)(something)+
将只捕获something
的第一次出现,而不是全部出现。解决这个问题的正确方法是编写一个与单个对匹配的正则表达式,并重复应用它,例如通过std::regex_迭代器
(Boost中可能有一个等价的正则表达式,我并不太熟悉)。正则表达式捕获的子字符串数量与表达式中左括号的数量完全相同(大致说来,非捕获组有一种语法,因此捕获可能比括号少,但不能多)。(某物)+
将只捕获第一次出现的某物,而不是全部。解决此问题的正确方法是编写一个与单个对匹配的正则表达式,并重复应用它,例如通过std::regex\u迭代器
(Boost中可能有一个等价的正则表达式,我并不太熟悉)。
#include <boost/fusion/adapted/std_pair.hpp> // reading maps
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <iostream>
#include <fstream>
#include <map>
auto read_config_map(std::istream& stream) {
std::map<std::string, std::string> settings;
boost::spirit::istream_iterator f(stream >> std::noskipws), l;
using namespace boost::spirit::x3;
auto key_ = lexeme [ +upper ];
auto value_ = lexeme [ '"' >> *~char_('"') >> '"' ];
if (!phrase_parse(f, l, -(key_ >> value_) % eol >> eoi, blank, settings))
throw std::invalid_argument("cannot parse config map");
return settings;
}
auto read_config_map(std::string const& fname) {
std::ifstream stream(fname);
return read_config_map(stream);
}
int main() {
for (auto&& entry : read_config_map(std::cin))
std::cout << "Key:'" << entry.first << "' Value:'" << entry.second << "'\n";
}
Key:'ANOTHERVALUE' Value:'bar'
Key:'VALUE' Value:'foo'
Key:'YETANOTHERVALUE' Value:'barbar'