gpt4 book ai didi

c++ - 如何使用 Boost 扩展 .ini 文件中的环境变量

转载 作者:太空狗 更新时间:2023-10-29 21:23:58 26 4
gpt4 key购买 nike

我有一个像这样的 INI 文件

[Section1]
Value1 = /home/%USER%/Desktop
Value2 = /home/%USER%/%SOME_ENV%/Test

并想使用 Boost 解析它。我尝试像这样使用 Boost property_tree

boost::property_tree::ptree pt;
boost::property_tree::ini_parser::read_ini("config.ini", pt);

std::cout << pt.get<std::string>("Section1.Value1") << std::endl;
std::cout << pt.get<std::string>("Section1.Value2") << std::endl;

但是并没有展开环境变量。输出看起来像

/home/%USER%/Desktop
/home/%USER%/%SOME_ENV%/Test

我期待的是这样的

/home/Maverick/Desktop
/home/Maverick/Doc/Test

我不确定是否可以使用 boost property_tree。

如果有任何使用 boost 解析此类文件的提示,我将不胜感激。

最佳答案

这是另一种方式,使用旧工艺:

  • 不需要Spirit,也不需要Boost
  • 不将接口(interface)硬连接到 std::string(而是允许输入迭代器输出迭代器 的任意组合)
  • %% 作为单个 % “正确”处理 1

本质:

#include <string>
#include <algorithm>

static std::string safe_getenv(std::string const& macro) {
auto var = getenv(macro.c_str());
return var? var : macro;
}

template <typename It, typename Out>
Out expand_env(It f, It l, Out o)
{
bool in_var = false;
std::string accum;
while (f!=l)
{
switch(auto ch = *f++)
{
case '%':
if (in_var || (*f!='%'))
{
in_var = !in_var;
if (in_var)
accum.clear();
else
{
accum = safe_getenv(accum);
o = std::copy(begin(accum), end(accum), o);
}
break;
} else
++f; // %% -> %
default:
if (in_var)
accum += ch;
else
*o++ = ch;
}
}
return o;
}

#include <iterator>

std::string expand_env(std::string const& input)
{
std::string result;
expand_env(begin(input), end(input), std::back_inserter(result));
return result;
}

#include <iostream>
#include <sstream>
#include <list>

int main()
{
// same use case as first answer, show `%%` escape
std::cout << "'" << expand_env("Greeti%%ng is %HOME% world!") << "'\n";

// can be done streaming, to any container
std::istringstream iss("Greeti%%ng is %HOME% world!");
std::list<char> some_target;

std::istreambuf_iterator<char> f(iss), l;
expand_env(f, l, std::back_inserter(some_target));
std::cout << "Streaming results: '" << std::string(begin(some_target), end(some_target)) << "'\n";

// some more edge cases uses to validate the algorithm (note `%%` doesn't
// act as escape if the first ends a 'pending' variable)
std::cout << "'" << expand_env("") << "'\n";
std::cout << "'" << expand_env("%HOME%") << "'\n";
std::cout << "'" << expand_env(" %HOME%") << "'\n";
std::cout << "'" << expand_env("%HOME% ") << "'\n";
std::cout << "'" << expand_env("%HOME%%HOME%") << "'\n";
std::cout << "'" << expand_env(" %HOME%%HOME% ") << "'\n";
std::cout << "'" << expand_env(" %HOME% %HOME% ") << "'\n";
}

在我的盒子上打印:

'Greeti%ng is /home/sehe world!'
Streaming results: 'Greeti%ng is /home/sehe world!'
''
'/home/sehe'
' /home/sehe'
'/home/sehe '
'/home/sehe/home/sehe'
' /home/sehe/home/sehe '
' /home/sehe /home/sehe '

1 当然,“适当”是主观的。至少,我认为这是

  • 会有用(否则您将如何配置一个合法包含 % 的值?)
  • cmd.exe 在 Windows 上是如何工作的

关于c++ - 如何使用 Boost 扩展 .ini 文件中的环境变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17112494/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com