2011-04-04 60 views
4

我一直在研究一個模仿shell終端的程序,並且遇到了比我預期的難的實現問題。基本上,我試圖分裂參數,很像shell如何傳遞給它的可執行文件。所以,想象的輸入,如:模仿C++中的shell參數解析器

$> ./foo some arguments

人們會期望傳遞給程序的參數像(假定C/C++)的陣列:

char ** argv = {"foo", "some" "arguments"}

然而,如果參數爲:

$> ./foo "My name is foo" bar

的陣列將是:

char ** argv = {"foo", "My name is foo", "bar"}

任何人都可以提出實現這一點,使得界面就像是一個有效的方法:

vector<string> splitArgs(string allArgs);string[] splitArgs(string allArgs);

我當然可以,只是重複和狀態之間切換'閱讀文字'/'閱讀引用文字',但我覺得那不是那麼有效。我也玩弄了正則表達式的想法,但我對C++中的這種做法還不夠熟悉。對於這個項目,我也安裝了boost庫,如果有幫助的話。

謝謝! RR

+2

「但是我覺得那樣做並不是那麼有效......」真的,你最好只是做這個工作並獲得一個工作shell。無論如何 - 因爲你問 - 使用boost tokenizer檢查http://stackoverflow.com/questions/541561/using-boost-tokenizer-escaped-list-separator-with-different-parameters解決方案。 – 2011-04-04 04:54:00

+0

只需通過每個角色,看看你有什麼。 [Here's](http://www.blackbeltcoder.com/Articles/strings/a-c-command-line-parser)我是如何在C#中完成的。我不確定RegEx會在這裏給你你需要的。 – 2011-04-04 04:58:08

+0

非常好,謝謝你們。我想這就是我想知道的。 – 2011-04-04 05:08:27

回答

0

我有時仍然使用這個簡單的C實用程序功能。我主要在嵌入式系統中使用它,因爲這些嵌入式系統的標準庫非常有限,所以大多數代碼可以通過使用標準庫控制來更改效率,但基本技術應該保持不變,標記引用的字符串部分在解析之前,只需通過分割標記來分離單獨的標記中的字符串,最後從各個部分中刪除引號。

/** 
* Split a line into separate words. 
*/ 
static void splitLine(char *pLine, char **pArgs) { 
    char *pTmp = strchr(pLine, ' '); 

    if (pTmp) { 
     *pTmp = '\0'; 
     pTmp++; 
     while ((*pTmp) && (*pTmp == ' ')) { 
      pTmp++; 
     } 
     if (*pTmp == '\0') { 
      pTmp = NULL; 
     } 
    } 
    *pArgs = pTmp; 
} 



/** 
* Breaks up a line into multiple arguments. 
* 
* @param io_pLine Line to be broken up. 
* @param o_pArgc Number of components found. 
* @param io_pargc Array of individual components 
*/ 
static void parseArguments(char *io_pLine, int *o_pArgc, char **o_pArgv) { 
    char *pNext = io_pLine; 
    size_t i; 
    int j; 
    int quoted = 0; 
    size_t len = strlen(io_pLine); 

    // Protect spaces inside quotes, but lose the quotes 
    for(i = 0; i < len; i++) { 
     if ((!quoted) && ('"' == io_pLine[i])) { 
      quoted = 1; 
      io_pLine[i] = ' '; 
     } else if ((quoted) && ('"' == io_pLine[i])) { 
      quoted = 0; 
      io_pLine[i] = ' '; 
     } else if ((quoted) && (' ' == io_pLine[i])) { 
      io_pLine[i] = '\1'; 
     } 
    } 

    // init 
    MY_memset(o_pArgv, 0x00, sizeof(char*) * C_MAXARGS); 
    *o_pArgc = 1; 
    o_pArgv[0] = io_pLine; 

    while ((NULL != pNext) && (*o_pArgc < C_MAXARGS)) { 
     splitLine(pNext, &(o_pArgv[*o_pArgc])); 
     pNext = o_pArgv[*o_pArgc]; 

     if (NULL != o_pArgv[*o_pArgc]) { 
      *o_pArgc += 1; 
     } 
    } 

    for(j = 0; j < *o_pArgc; j++) { 
     len = strlen(o_pArgv[j]); 
     for(i = 0; i < len; i++) { 
      if('\1' == o_pArgv[j][i]) { 
       o_pArgv[j][i] = ' '; 
      } 
     } 
    } 
}