我想知道是否有一种优雅的方法来解析C ++中的典型配置文件。
# This is a comment
log =/var/log/secure
max_tries=5
max_reports=2
以下是我目前的情况:
std::string buf;
smatch matches;
int line_number = 0; // keeping track of the line number allows for error identification
std::unordered_map<std::string, std::string> parsed_options;
while (std::getline(is, buf)) {
// is the line a comment or blank?
if ((buf.find_first_of('#') == 0) || (std::all_of(buf.begin(), buf.end(), isspace)) || (buf.empty())) {
} else {
std::istringstream configs(buf);
std::string option;
if (std::getline(configs, option, '=')) {
std::string val;
if (std::getline(configs, val)) {
option.erase(std::remove_if(option.begin(), option.end(), isspace), option.end());
val.erase(std::remove_if(val.begin(), val.end(), isspace), val.end());
parsed_options.emplace(std::make_pair(option, val));
}
} else {
std::stringstream se;
se << "Coud not parse option at line " << line_number;
throw std::runtime_error(se.str());
}
}
++line_number;
}
for (auto i : parsed_options) {
if (i.first == "log") {
auth_log_ = i.second;
} else if (i.first == "max_tries") {
max_attempts_ = std::stoi(i.second);
} else if (i.first == "max_reports") {
max_reports_ = std::stoi(i.second);
} else if (i.first == "interval") {
interval_ == std::stoi(i.second);
} else {
std::cout << "\"" << i.first << "\" " << i.second << '\n';
std::stringstream ss1;
ss1 << "Invalid option at line " << line_number;
throw std::runtime_error(ss1.str());
}
}
}
虽然这有效,但我有一个问题。我想添加对所谓“部分”的支持。
# This is a comment
[section1]
log =/var/log/secure
max_tries=5
max_reports=2
[section2]
log =/var/log/secure
max_tries=5
max_reports=2
鉴于此配置文件,我理想情况下可以分别解析这些部分。最终我将需要它,我可以阅读部分名称,并使用每个部分下的选项没有冲突。如果每个部分下的名称与另一个部分的名称相匹配,我需要能够从两个部分中提取值而不会遇到问题。我宁愿不使用Boost看到我更喜欢STL,但如果证明它更快更有效,我将使用它。