2009-12-14 36 views
18

什么是最好的方式来扩大展开在他们的道路环境变量文件名

${MyPath}/filename.txt to /home/user/filename.txt 

%MyPath%/filename.txt to c:\Documents and settings\user\filename.txt 

与出穿越路径字符串寻找直接environement变量? 我看到wxWidgets具有wxExpandEnvVars函数。在这种情况下,我不能使用wxWidgets,所以我希望找到一个boost :: filesystem等效或类似的东西。我只使用主目录作为例子,我正在寻找通用路径扩展。

回答

16

在Windows上,您可以使用ExpandEnvironmentStrings。不确定Unix的等价物。

+0

Thanks Rob。这让我一半在那里。我想我会研究非窗口案例的解析方法。 – Dan 2009-12-15 13:08:40

19

对于UNIX(或者至少POSIX)系统,看看wordexp

#include <iostream> 
#include <wordexp.h> 
using namespace std; 
int main() { 
    wordexp_t p; 
    char** w; 
    wordexp("$HOME/bin", &p, 0); 
    w = p.we_wordv; 
    for (size_t i=0; i<p.we_wordc;i++) cout << w[i] << endl; 
    wordfree(&p); 
    return 0; 
} 

看来它甚至会做水珠般的扩张(这可能会或可能不适合你的特殊情况非常有用) 。

+0

对我而言,这是另一半。上述解决方案同时适用于Posix和Window。 – xryl669 2013-05-27 17:00:52

+1

如果可以的话,我会加倍努力。使用系统提供的设施很好的答案,它肯定比正则表达式更不容易出错。 – 2014-09-19 06:19:48

3

在C/C++语言中,这是我在Unix下解决环境变量的方法。 fs_parm指针将包含要扩展的可能环境变量的filespec(或文本)。 wrkSpc指向的空间必须是MAX_PATH + 60个字符长。 echo字符串中的双引号是为了防止处理通配符。大多数默认shell应该能够处理这个。


    FILE *fp1; 

    sprintf(wrkSpc, "echo \"%s\" 2>/dev/null", fs_parm); 
    if ((fp1 = popen(wrkSpc, "r")) == NULL || /* do echo cmd  */ 
     fgets(wrkSpc, MAX_NAME, fp1) == NULL)/* Get echo results */ 
    {      /* open/get pipe failed    */ 
    pclose(fp1);   /* close pipe      */ 
    return (P_ERROR);  /* pipe function failed    */ 
    } 
    pclose(fp1);    /* close pipe      */ 
    wrkSpc[strlen(wrkSpc)-1] = '\0';/* remove newline   */ 

对于MS Windows,请使用ExpandEnvironmentStrings()函数。

1

这是我用:

const unsigned short expandEnvVars(std::string& original) 
{ 
    const boost::regex envscan("%([0-9A-Za-z\\/]*)%"); 
    const boost::sregex_iterator end; 
    typedef std::list<std::tuple<const std::string,const std::string>> t2StrLst; 
    t2StrLst replacements; 
    for (boost::sregex_iterator rit(original.begin(), original.end(), envscan); rit != end; ++rit) 
     replacements.push_back(std::make_pair((*rit)[0],(*rit)[1])); 
    unsigned short cnt = 0; 
    for (t2StrLst::const_iterator lit = replacements.begin(); lit != replacements.end(); ++lit) 
    { 
     const char* expanded = std::getenv(std::get<1>(*lit).c_str()); 
     if (expanded == NULL) 
      continue; 
     boost::replace_all(original, std::get<0>(*lit), expanded); 
     cnt++; 
    } 
    return cnt; 
} 
1

随着问题被标记为“wxWidgets的”,你可以使用它的环境变量扩展使用wxConfigwxExpandEnvVars()功能。该功能本身不幸没有记录,但它基本上做你认为它应该和扩展在所有平台上$VAR,$(VAR),$(VAR)${VAR}%VAR%在Windows下的任何事件。

-1

由于问题标记为C++,因此您可以使用标准getenv,并用标准C++ 11 regex来替换该变量的值。

6

简单便携:

#include <cstdlib> 
#include <string> 

static std::string expand_environment_variables(const std::string &s) { 
    if(s.find("${") == std::string::npos) return s; 

    std::string pre = s.substr(0, s.find("${")); 
    std::string post = s.substr(s.find("${") + 2); 

    if(post.find('}') == std::string::npos) return s; 

    std::string variable = post.substr(0, post.find('}')); 
    std::string value = ""; 

    post = post.substr(post.find('}') + 1); 

    const *v = getenv(variable.c_str()); 
    if(v != NULL) value = std::string(v); 

    return expand_environment_variables(pre + value + post); 
} 

expand_environment_variables("${HOME}/.myconfigfile");产生/home/joe/.myconfigfile

+0

请注意,这只会扩展单个环境变量。这个例子是可以的。如果您需要在一个字符串中扩展多个环境变量,请在post后递归调用expane_environment_variables。 – tbleher 2014-07-07 13:09:09

+1

注意:为了得到相同的var,你需要调用'getenv(variable.c_str())'两次,最好存储结果。 – vladon 2015-09-06 19:10:00

0

使用Qt,这对我的作品:

#include <QString> 
#include <QRegExp> 

QString expand_environment_variables(QString s) 
{ 
    QString r(s); 
    QRegExp env_var("\\$([A-Za-z0-9_]+)"); 
    int i; 

    while((i = env_var.indexIn(r)) != -1) { 
     QByteArray value(qgetenv(env_var.cap(1).toLatin1().data())); 
     if(value.size() > 0) { 
      r.remove(i, env_var.matchedLength()); 
      r.insert(i, value); 
     } else 
      break; 
    } 
    return r; 
} 

expand_environment_variables(QString的( “$ HOME/.myconfigfile”)) ; yield /home/martin/.myconfigfile (它也适用于嵌套扩展)

5

如果您有使用C++ 11的奢侈,那么正则表达式非常方便。我写了一个更新版本和声明版本。

#include <string> 
#include <regex> 

// Update the input string. 
void autoExpandEnvironmentVariables(std::string & text) { 
    static std::regex env("\\$\\{([^}]+)\\}"); 
    std::smatch match; 
    while (std::regex_search(text, match, env)) { 
     const char * s = getenv(match[1].str().c_str()); 
     const std::string var(s == NULL ? "" : s); 
     text.replace(match[0].first, match[0].second, var); 
    } 
} 

// Leave input alone and return new string. 
std::string expandEnvironmentVariables(const std::string & input) { 
    std::string text = input; 
    autoExpandEnvironmentVariables(text); 
    return text; 
} 

这种方法的一个优点是它可以很容易地适应句法变化并处理宽字符串。 (使用Clang在OS X上编译并使用flag -std = C++ 0x进行测试)

+0

g ++ 4.9.3(Ubuntu)无法编译,它与iterator和const_iterator之间的转换有关。我必须改变text.replace(match [0] .first,match [0] .second,var);到text.replace(match.position(0),match.length(0),var); – fchen 2016-03-24 15:38:13