【问题标题】:Parsing Command Line Arguments in C在 C 中解析命令行参数
【发布时间】:2013-03-07 09:12:27
【问题描述】:

我正在尝试实现一个程序,该程序接受一个进程,后跟一个由管道命令组成的字符串。如何将命令字符串分隔为{单个命令/任意数量的参数数组}“|”是分隔不同命令的字符。

例如,如果我输入: 管道 ls -lt |猫 Lebowski |光盘...

我如何让系统识别这里有三个单独的命令行参数以不同的管道表示。

【问题讨论】:

  • 看看strtok

标签: c parsing command-line pipe


【解决方案1】:

首先,由于管道是一个特殊符号,因此在传递给程序时需要对其进行转义:

pipe ls -lt \| cat Lebowski \| cd .. .

在你的主要功能中:

main(int argc, char *argv[]) {

argv 在不同的索引处包含所有这些参数(ls、-lt、|、cat...)。例如,argv[0]lsargv[2]'|'argc 是此类参数的总数。

【讨论】:

  • 您回复的第一行概述了我需要发生的事情。我必须在没有“\”分隔参数的情况下解析参数
  • 所以您正在实现一个外壳并使用 scanf 或类似方法读取输入?在这种情况下,H2CO3 的答案是一个
【解决方案2】:

如果您想自己执行此操作,perreal 的回答非常好。有一个函数 getopt() 也可以用于此目的,并在此处记录 getopt()

【讨论】:

    【解决方案3】:

    strtok_r() 函数是你的朋友:

    char **explode(char *s, const char *sep, size_t *outsz)
    {
        size_t allocsz = 4;
        size_t sz = 0;
        char **arr = malloc(allocsz * sizeof(*arr));
        if (arr == NULL) {
            *outsz = 0;
            return NULL;
        }
    
        char *p, *end;
        for (p = srtok_r(s, sep, &end); p; p = strtok_r(NULL, sep, &end)) {
            if (++sz > allocsz) {
                allocsz <<= 1;
                arr = realloc(arr, sizeof(*arr) * allocsz));
                assert(arr != NULL); // sorry
            }
            arr[sz - 1] = strdup(p);
        }
    
        *outsz = sz;
        return arr;
    }
    

    用法:

    int main()
    {
        char sentence[] = "The quick brown fox jumped over the lazy dog.";
        size_t sz;
        char **arr = explode(sentence, " ", &sz);
        int i;
        for (i = 0; i < sz; i++) {
            printf("%s\n", arr[i]);
            free(arr[i]);
        }
        free(arr);
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      自从 |是大多数常见 shell 的特殊字符,您需要引用它们(正如其他人所说)。如果您引用双引号内的所有参数,例如

      管道 "ls -lt | cat Lebowski | cd .."

      你可以用strtok_r()解析argv[1]

      【讨论】:

      • 我讨厌让 cmets 谈论安全等问题,但请不要建议使用 strtok() strtok_r() 是安全(特别是可重入)变体。
      • @H2CO3 感谢您的建议。很久没有做纯C编程了。
      • @H2CO3 根据您的建议修复 ;-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-31
      • 2010-10-26
      • 2021-07-27
      相关资源
      最近更新 更多