2009-12-14 34 views
18

Có gì cách tốt nhất để mở rộngmở rộng tên tập tin đó có các biến môi trường trong con đường của mình

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

hoặc

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

với ra đi qua chuỗi con đường tìm kiếm các biến environement trực tiếp? Tôi thấy rằng wxWidgets có chức năng wxExpandEnvVars. Tôi không thể sử dụng wxWidgets trong trường hợp này, vì vậy tôi đã hy vọng tìm thấy một tăng :: hệ thống tập tin tương đương hoặc tương tự. Tôi chỉ sử dụng thư mục chính làm ví dụ, tôi đang tìm cách mở rộng đường dẫn mục đích chung.

Trả lời

16

Trên Windows, bạn có thể sử dụng ExpandEnvironmentStrings. Không chắc chắn về một Unix tương đương được nêu ra.

+0

Cảm ơn Rob. Điều này giúp tôi một nửa ở đó. Tôi đoán tôi sẽ xem xét phương pháp phân tích cú pháp cho các trường hợp không cửa sổ. – Dan

19

Đối với hệ thống UNIX (hoặc ít nhất là POSIX), có một cái nhìn tại 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; 
} 

Có vẻ như nó thậm chí sẽ làm mở rộng glob-like (mà có thể hoặc không có thể hữu ích cho tình hình cụ thể của bạn) .

+0

Đối với tôi, đây là một nửa khác. Giải pháp này với giải pháp trên làm việc trên cả Posix và Window. – xryl669

+1

Tôi sẽ upvote này ba lần nếu tôi có thể. Câu trả lời tuyệt vời bằng cách sử dụng các cơ sở được hệ thống cung cấp mà chắc chắn ít bị lỗi hơn các công cụ regex. –

3

Trong ngôn ngữ C/C++, dưới đây là những gì tôi làm để giải quyết các biến môi trường trong Unix. Con trỏ fs_parm sẽ chứa các filespec (hoặc văn bản) của các biến môi trường có thể được mở rộng. Không gian wrkSpc trỏ đến phải dài MAX_PATH + 60 ký tự. Các dấu ngoặc kép trong chuỗi echo là để ngăn chặn các thẻ hoang dã được xử lý. Hầu hết các shell mặc định sẽ có thể xử lý điều này.


    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   */ 

Đối với MS Windows, sử dụng chức năng ExpandEnvironmentStrings().

1

Đây là những gì tôi sử dụng:

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

Như câu hỏi được gắn thẻ "wxWidgets", bạn có thể sử dụng chức năng wxExpandEnvVars() sử dụng bởi wxConfig để mở rộng biến môi trường của nó. Bản thân chức năng không may là không được ghi lại, nhưng về cơ bản nó làm những gì bạn nghĩ nó nên và mở rộng bất kỳ sự xuất hiện của $VAR, $(VAR) hoặc ${VAR} trên tất cả các nền tảng và cũng là %VAR% chỉ trong Windows.

-1

Khi câu hỏi được gắn thẻ C++, bạn có thể sử dụng tiêu chuẩn getenv, với một lần chạm tiêu chuẩn C++ 11 regex để thay thế biến theo giá trị của nó.

6

đơn giản và di động:

#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"); mang /home/joe/.myconfigfile

+0

Lưu ý rằng điều này chỉ mở rộng một biến môi trường duy nhất. Đó là OK cho ví dụ. Nếu bạn cần mở rộng nhiều biến môi trường trong một chuỗi, hãy gọi hàm expane_environment_variables đệ quy trên bài đăng. – tbleher

+1

Lưu ý: bạn gọi 'getenv (variable.c_str())' hai lần để nhận được cùng một var, tốt hơn để lưu trữ kết quả. – vladon

0

Sử dụng Qt, công trình này cho tôi:

#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")) ; yields /home/martin/.myconfigfile (Nó cũng hoạt động với các phần mở rộng lồng nhau)

5

Nếu bạn có sự sang trọng của việc sử dụng C++ 11, thì biểu thức thông thường khá tiện dụng. Tôi đã viết một phiên bản để cập nhật tại chỗ và một phiên bản khai báo.

#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; 
} 

Ưu điểm của phương pháp này là có thể dễ dàng điều chỉnh dễ dàng để đối phó với các biến thể cú pháp và xử lý chuỗi rộng. (Biên dịch và thử nghiệm bằng Clang trên OS X với cờ -std = C++ 0x)

+0

g ++ 4.9.3 (Ubuntu) không thể biên dịch, đó là một cái gì đó liên quan đến chuyển đổi giữa iterator và const_iterator. Tôi phải thay đổi text.replace (match [0] .first, match [0] .second, var); thành text.replace (match.position (0), match.length (0), var); – fchen

Các vấn đề liên quan