expand file names that have environment variables in their path

后端 未结 8 2038
礼貌的吻别
礼貌的吻别 2020-12-01 08:06

What\'s the best way to expand

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

or

%MyPath%/filename.txt to c:\\Document         


        
相关标签:
8条回答
  • 2020-12-01 08:25

    On Windows, you can use ExpandEnvironmentStrings. Not sure about a Unix equivalent yet.

    0 讨论(0)
  • 2020-12-01 08:32

    Within the C/C++ language, here is what I do to resolve environmental variables under Unix. The fs_parm pointer would contain the filespec (or text) of possible environmental variables to be expanded. The space that wrkSpc points to must be MAX_PATH+60 chars long. The double quotes in the echo string are to prevent the wild cards from being processed. Most default shells should be able to handle this.

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

    For MS Windows, use the ExpandEnvironmentStrings() function.

    0 讨论(0)
  • 2020-12-01 08:34

    Using Qt, this works for me:

    #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 (It also works with nested expansions)

    0 讨论(0)
  • 2020-12-01 08:36

    Simple and portable:

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

    0 讨论(0)
  • 2020-12-01 08:37

    If you have the luxury of using C++11, then regular expressions are quite handy. I wrote a version for updating in place and a declarative version.

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

    An advantage of this approach is that it can be adapted easily to cope with syntactic variations and deal with wide strings too. (Compiled and tested using Clang on OS X with the flag -std=c++0x)

    0 讨论(0)
  • 2020-12-01 08:42

    This is what I use:

    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;
    }
    
    0 讨论(0)
提交回复
热议问题