我想在shell脚本中解析长选项。 POSIX仅提供getopts
来解析单个字母选项。有没有人知道在shell中实现长选项解析的可移植(POSIX)方法?我已经看过autoconf
生成configure
脚本时的作用,但结果远非优雅。我只能接受长选项的完整拼写。仍应允许单字母选项,可能是分组。
我正在考虑一个shell函数,它采用空格分隔的形式选项[= flags]的args列表,其中标志表示该选项采用arg或可以多次指定。与C对应物不同,不需要区分字符串,整数和浮点数。
答案 0 :(得分:2)
getopt_long
命令我有一个程序getoptx
,它使用单字母选项(因此它不是您的问题的答案),但它正确处理带空格的参数,原始getopt
命令(如与内置getopts
)相反的shell没有。源代码中的规范说:
/*
** Usage: eval set -- $(getoptx abc: "$@")
** eval set -- $(getoptx abc: -a -c 'a b c' -b abc 'd e f')
** The positional parameters are:
** $1 = "-a"
** $2 = "-c"
** $3 = "a b c"
** $4 = "-b"
** $5 = "--"
** $6 = "abc"
** $7 = "d e f"
**
** The advantage of this over the standard getopt program is that it handles
** spaces and other metacharacters (including single quotes) in the option
** values and other arguments. The standard code does not! The downside is
** the non-standard invocation syntax compared with:
**
** set -- $(getopt abc: "$@")
*/
我建议您eval set -- $(getopt_long "$optspec" "$@")
使用getopt_long
表示法。
getopt_long
的一个主要问题是参数规范的复杂性 - 示例中的$optspec
。
您可能希望查看Solaris CLIP(命令行界面范例)中使用的符号表示法;它使用单个字符串(如原始getopt()
函数)来描述选项。 (Google:'solaris clip命令行界面范例';只使用'solaris剪辑'可以获得视频剪辑。)
此材料是源自Sun的getopt_clip()
:
/*
Example 2: Check Options and Arguments.
The following example parses a set of command line options and prints
messages to standard output for each option and argument that it
encounters.
This example can be expanded to be CLIP-compliant by substituting the
long string for the optstring argument:
While not encouraged by the CLIP specification, multiple long-option
aliases can also be assigned as shown in the following example:
:a(ascii)b(binary):(in-file)(input)o:(outfile)(output)V(version)?(help)
*/
static const char *arg0 = 0;
static void print_help(void)
{
printf("Usage: %s [-a][-b][-V][-?][-f file][-o file][path ...]\n", arg0);
printf("Usage: %s [-ascii][-binary][-version][-in-file file][-out-file file][path ...]\n", arg0);
exit(0);
}
static const char optstr[] =
":a(ascii)b(binary)f:(in-file)o:(out-file)V(version)?(help)";
int main(int argc, char **argv)
{
int c;
char *filename;
arg0 = argv[0];
while ((c = getopt_clip(argc, argv, optstr)) != -1)
{
...
}
...
}