【发布时间】:2018-03-23 23:07:57
【问题描述】:
我正在为我开发的类似 bash 的 shell 编写一个选项解析器。
不过,为了与 bash 选项兼容,我必须阅读一些以“+”开头的选项,如下所示:
./42sh +O autocd [...]
(手册页说这些选项将传递给设置设置值的内置shopt)。
问题是getopt_long() 函数只返回以- 或-- 开头的选项,如果它们不是单独的。如果是,则 bash 将它们分别视为标准输入的别名和选项结束标记。
如何使用 getopt_long() 获得此类选项?我必须自己解析这些选项吗?
编辑:根据@jxh 响应和man 3 getopt 页面,我发现getopt 和getopt_long 排列**argv 参数数组以移动所有似乎不是有效选项的参数 - 从他们的观点 - 最后。因此,我在获得 normal 选项的常用代码之后编写了以下代码(非常感谢所有建议和评论):
EDIT2 : 修复了由于 strdup() 在循环的每次迭代中导致的内存泄漏。
for(; optind < argc; ++optind)
{
const char *argv_copy = strdup(argv[optind]);
if (argv_copy[0] == '+' && argv_copy[1] == 'O')
{
/* A deactivation parameter have been just found ! */
if (handle_shopt_options(shell_options,
argv[optind + 1],
DISABLE) == EXIT_FAILURE)
{
usage(argv[optind]);
free_shell_options(shell_options);
shell_options = NULL;
}
++optind;
}
free(argv_copy);
argv_copy = NULL;
}
一些解释:
-
optind是argv索引,它告诉我们哪个参数将在下一次传递中被解析。由于我们解析了所有 getopt() 观点的有效参数,并且由于 getopt() 在最后移动了所有非选项,我们将解析所有剩余的参数,包括我们感兴趣的参数。 -
argv[argc] == NULL:这个技巧是用来知道参数列表的末尾在哪里,所以在optind == argc时解析参数是没有用的。 - 我不习惯直接使用当前的
argv值,所以我更喜欢将它复制到一个新字符串中,但我可能错了,需要验证。
一些备注:
-
仅当定义了
_GNU_SOURCE宏时,getopt_long()才可用。 -
strdup()仅在宏_XOPEN_SOURCE >= 500或宏_POSIX_C_SOURCE >= 200809L时可用。
【问题讨论】:
标签: c bash c99 getopt getopt-long