将命令行字符串解析为argv格式

时间:2011-12-23 08:39:38

标签: c++ c linux exec

我需要将命令行字符串解析为argv格式,以便将其传递给execvpe。基本上一个Linux与Windows的CommandLineToArgvW()等效。我可以打电话来做这个功能或库吗?或者我是否必须编写自己的解析器? (我希望如果我需要这样做,我可以从BASH偷走,因为我的程序是GPL ......)

实施例: 我有三个变量:

const char* file = "someapplication";
const char* parameters = "param1 -option1 param2";
const char* environment[] = { "Something=something", NULL };

我希望将它传递给execvpe:

execvpe(file, /* parsed parameters */, environment);

PS:我不想要文件名扩展,但我想引用和转义

5 个答案:

答案 0 :(得分:3)

我在评论(http://bbgen.net/blog/2011/06/string-to-argc-argv)中使用了rve给出的链接,这解决了我的问题。提出他的评论,而不是我的回答!

答案 1 :(得分:1)

使用我的nargv程序。我真的用这个答案将这个问题打败了:https://stackoverflow.com/a/10071763/735796 nargv意味着新的参数向量。它支持shell将字符串解析为单独元素的所有内容。例如,它支持双引号,单引号和字符串连接。

答案 2 :(得分:0)

char *strtok(char *s, const char *delim)正是您要找的

char *s将是标准输入,char *delim将是' '

答案 3 :(得分:0)

也许我错过了一些东西,但为什么不把&argv[1]作为参数和使用getenv()获得的环境作为环境传递?

修改 如果需要不同的分隔符,可以使用环境变量IFS(内部字段分隔符)来实现此目的。

答案 4 :(得分:0)

以下是我第一次尝试复制Windows shell库中CommandLineToArgvW()函数的功能。它仅使用标准函数和类型,不使用Boost。除了对strdup()的一次调用外,它与平台无关,适用于Windows和Linux环境。它处理单引号或双引号的参数。

// Snippet copied from a larger file.  I hope I added all the necessary includes.
#include <string>
#include <string.h>
#include <vector>

using namespace std;

char ** CommandLineToArgv( string const & line, int & argc )
{
    typedef vector<char *> CharPtrVector;
    char const * WHITESPACE_STR = " \n\r\t";
    char const SPACE = ' ';
    char const TAB = '\t';
    char const DQUOTE = '\"';
    char const SQUOTE = '\'';
    char const TERM = '\0';


    //--------------------------------------------------------------------------
    // Copy the command line string to a character array.
    // strdup() uses malloc() to get memory for the new string.
#if defined( WIN32 )
    char * pLine = _strdup( line.c_str() );
#else
    char * pLine = strdup( line.c_str() );
#endif


    //--------------------------------------------------------------------------
    // Crawl the character array and tokenize in place.
    CharPtrVector tokens;
    char * pCursor = pLine;
    while ( *pCursor )
    {
        // Whitespace.
        if ( *pCursor == SPACE || *pCursor == TAB )
        {
            ++pCursor;
        }

        // Double quoted token.
        else if ( *pCursor == DQUOTE )
        {
            // Begin of token is one char past the begin quote.
            // Replace the quote with whitespace.
            tokens.push_back( pCursor + 1 );
            *pCursor = SPACE;

            char * pEnd = strchr( pCursor + 1, DQUOTE );
            if ( pEnd )
            {
                // End of token is one char before the end quote.
                // Replace the quote with terminator, and advance cursor.
                *pEnd = TERM;
                pCursor = pEnd + 1;
            }
            else
            {
                // End of token is end of line.
                break;
            }
        }

        // Single quoted token.
        else if ( *pCursor == SQUOTE )
        {
            // Begin of token is one char past the begin quote.
            // Replace the quote with whitespace.
            tokens.push_back( pCursor + 1 );
            *pCursor = SPACE;

            char * pEnd = strchr( pCursor + 1, SQUOTE );
            if ( pEnd )
            {
                // End of token is one char before the end quote.
                // Replace the quote with terminator, and advance cursor.
                *pEnd = TERM;
                pCursor = pEnd + 1;
            }
            else
            {
                // End of token is end of line.
                break;
            }   
        }

        // Unquoted token.
        else
        {
            // Begin of token is at cursor.
            tokens.push_back( pCursor );

            char * pEnd = strpbrk( pCursor + 1, WHITESPACE_STR );
            if ( pEnd )
            {
                // End of token is one char before the next whitespace.
                // Replace whitespace with terminator, and advance cursor.
                *pEnd = TERM;
                pCursor = pEnd + 1;
            }
            else
            {
                // End of token is end of line.
                break;
            }
        }
    }


    //--------------------------------------------------------------------------
    // Fill the argv array.
    argc = tokens.size();
    char ** argv = static_cast<char **>( malloc( argc * sizeof( char * ) ) );
    int a = 0;
    for ( CharPtrVector::const_iterator it = tokens.begin(); it != tokens.end(); ++it )
    {
        argv[ a++ ] = (*it);
    }


    return argv;
}