diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f21f01..e366cc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ TARGET_SOURCES( rvstd PRIVATE "src/rvstd/boost_json_ext.cpp" + "src/rvstd/envsubst.cpp" "src/rvstd/unique_identifier.cpp" "src/rvstd/tableau.cpp" "src/rvstd/options.cpp" diff --git a/include/rvstd/envsubst.hpp b/include/rvstd/envsubst.hpp new file mode 100644 index 0000000..a3fca2f --- /dev/null +++ b/include/rvstd/envsubst.hpp @@ -0,0 +1,16 @@ +#ifndef RVSTD_ENVSUBST_HPP +#define RVSTD_ENVSUBST_HPP + +#include + +#include +#include +#include + +namespace rvstd { + +auto envsubst(const std::string& text) -> std::string; + +} // namespace rvstd + +#endif // RYJSOND_ENVSUBST_HPP diff --git a/src/rvstd/envsubst.cpp b/src/rvstd/envsubst.cpp new file mode 100644 index 0000000..7518b28 --- /dev/null +++ b/src/rvstd/envsubst.cpp @@ -0,0 +1,35 @@ +#include "rvstd/envsubst.hpp" + +#include + +#include + +namespace rvstd { + +auto envsubst(const std::string& text) -> std::string +{ + static const boost::regex env_var_pattern{R"--(\$(?:(\w+)|\{([^}]+)\}))--"}; + std::ostringstream result; + boost::regex_replace( + std::ostreambuf_iterator(result), + text.begin(), + text.end(), + env_var_pattern, + [&](const boost::match_results& match) { + std::string var_name_str; + if(match[1].matched) { + var_name_str = match[1].str(); + } + else if(match[2].matched) { + var_name_str = match[2].str(); + } + if(const char* ptr = std::getenv(var_name_str.c_str()); ptr != nullptr) { + return ptr; + } + return ""; // Empty string for non-existent variables + }); + + return result.str(); // Return the result stored in the output stream +} + +} // namespace rvstd