2009-12-14 38 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