如何在你的Bash shell脚本中包含选项

364 阅读2分钟

终端命令通常有选项或开关,你可以用它们来修改该命令如何做它所做的事情。选项包括在命令行界面的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让它变得简单。