2011-12-23 117 views
3

我需要将命令行字符串解析为argv格式,以便我可以将它传递给execvpe。基本上从Windows平等到CommandLineToArgvW()。有什么功能或图书馆我可以打电话来做到这一点?还是我必须编写我自己的解析器? (我希望我可以从BASH偷,如果我需要做,因为我的程序是GPL ...)将命令行字符串解析为argv格式

例子: 我有三个变量:

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

,我想将它传递给execvpe:

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

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

+0

见的http://stackoverflow.com/a/3848603/12711 – 2011-12-23 08:47:35

+0

可能重复的[解析串入的argv /的argc(http://stackoverflow.com/questions/1706551/parse-string-into -argv-argc) – ChrisWue 2011-12-23 08:51:41

+0

你能解释一下'wordexp()'吗?我不明白这是手册页:/ – 2011-12-23 08:59:07

回答

3

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

+0

给出的链接已打破 – Joakim 2015-02-28 23:15:41

+1

网络存档获得它:http://web.archive.org/web/20121030075237/http://bbgen.net/blog/2011/06/string-to-argc-argv – 2015-03-01 10:14:06

0

char *strtok(char *s, const char *delim)是你在找什么

char *s将标准输入和char *delim' '

+0

但是如果's'有''' (反斜杠空间)在什么地方? – 2011-12-23 08:48:14

+0

这将不会处理引用(或globbing或任何其他类似shell的行为,除了分隔空间)。目前尚不清楚OP是否需要(尽管提到bash),但我认为至少引用可能很重要。 – 2011-12-23 08:51:11

+0

噢,好吧,我不明白这一点。 是的,它不会处理特殊字符,引用等。 – rxdazn 2011-12-23 08:55:46

0

也许我失去了一些东西,但你为什么不只是传递&argv[1]作为参数,并使用getenv()为环境所获得的环境?

编辑: 如果你想有一个不同的分隔符,你可以使用环境变量IFS(内部字段分隔符)来实现这一目标。

+0

我假设他有兴趣传递一些以字符串形式出现的参数(可能来自文件或交互式输入)。 – 2011-12-23 08:52:51

+0

听起来很合理,我添加了关于IFS的说明,这可能也有帮助。 – stativ 2011-12-23 08:55:17

1

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

+0

它甚至有语法错误报告。 – 2012-04-09 10:59:18

+1

但是你仍然没有链接到实际的项目。你上面提到的问题没有提及在哪里找到它......这里是:https://github.com/hypersoft/nargv – Joakim 2015-03-01 11:14:55

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; 
} 
相关问题