终端命令通常具有选项或开关,您可以使用它们来修改命令的执行方式。 选项包含在命令行界面的POSIX 规范中。 这也是最早的 UNIX 应用程序建立的悠久惯例,因此了解如何在创建自己的命令时将其包含在Bash 脚本中非常重要。
与大多数语言一样,有几种方法可以解决 Bash 中解析选项的问题。 直到今天,我最喜欢的方法仍然是我从 Patrick Volkerding 的 Slackware 构建脚本中学到的方法,它是我第一次发现 Linux 并敢于冒险进入操作系统附带的纯文本文件时,我对 shell 脚本的介绍。
Bash 中的选项解析
在 Bash 中解析选项的策略是循环遍历传递给 shell 脚本的所有参数,确定它们是否是选项,然后转移到下一个参数。 重复此过程,直到没有剩余选项。
从一个简单的布尔选项(有时称为开关或标志)开始
#!/bin/bash
while [ True ]; do
if [ "$1" = "--alpha" -o "$1" = "-a" ]; then
ALPHA=1
shift 1
else
break
fi
done
echo $ALPHA
在此代码中,我创建了一个 while
循环,该循环充当无限循环,直到没有更多参数要处理。 if
语句尝试将第一个位置 ($1
) 中找到的任何参数与 --alpha
或 -a
匹配。 (这些是任意选项名称,没有特殊意义。在实际脚本中,您可以使用 --verbose
和 -v
来触发详细输出)。
shift
关键字导致所有参数移动 1 位,以便位置 2 ($2
) 中的参数移动到位置 1 ($1
)。 当没有更多参数要处理时,将触发 else
语句,这会中断 while
循环。
在脚本的末尾,$ALPHA
的值打印到终端。
测试脚本
$ bash ./test.sh --alpha
1
$ bash ./test.sh
$ bash ./test.sh -a
1
正确检测到该选项。
在 Bash 中检测参数
但是,存在一个问题:额外的参数被忽略了。
$ bash ./test.sh --alpha foo
1
$
要捕获不打算作为选项的参数,您可以将剩余参数转储到 Bash 数组中。
#!/bin/bash
while [ True ]; do
if [ "$1" = "--alpha" -o "$1" = "-a" ]; then
ALPHA=1
shift 1
else
break
fi
done
echo $ALPHA
ARG=( "${@}" )
for i in ${ARG[@]}; do
echo $i
done
测试新版本的脚本
$ bash ./test.sh --alpha foo
1
foo
$ bash ./test.sh foo
foo
$ bash ./test.sh --alpha foo bar
1
foo
bar
带有参数的选项
某些选项需要自己的参数。 例如,您可能希望允许用户设置属性,例如颜色或图形分辨率,或者将您的应用程序指向自定义配置文件。
要在 Bash 中实现这一点,您可以使用 shift
关键字,就像使用布尔开关一样,但将参数移动 2 而不是 1。
#!/bin/bash
while [ True ]; do
if [ "$1" = "--alpha" -o "$1" = "-a" ]; then
ALPHA=1
shift 1
elif [ "$1" = "--config" -o "$1" = "-c" ]; then
CONFIG=$2
shift 2
else
break
fi
done
echo $ALPHA
echo $CONFIG
ARG=( "${@}" )
for i in ${ARG[@]}; do
echo $i
done
在此代码中,我添加了一个 elif
子句,以将每个参数与 --config
和 -c
进行比较。 如果匹配,则名为 CONFIG
的变量的值设置为第二个参数的值(这意味着 --config
选项需要一个参数)。 所有参数都移动 2 位:1 位用于移动 --config
或 -c
,1 位用于移动其参数。 像往常一样,循环重复,直到没有剩余匹配参数。
这是新版本脚本的测试
$ bash ./test.sh --config my.conf foo bar
my.conf
foo
bar
$ bash ./test.sh -a --config my.conf baz
1
my.conf
baz
简化选项解析
还有其他方法可以在 Bash 中解析选项。 您可以交替使用 case
语句或 getopt
命令。 无论您选择使用什么,用户的选项对于任何应用程序来说都是重要的功能,而 Bash 使之变得容易。
评论已关闭。