跳至内容

Bash Shell 脚本/位置参数

来自维基教科书,开放的书籍,开放的世界

在上面大多数命令中——无论是执行内置命令,还是使用外部程序——我们都提供了一个或多个 *参数*,这些参数指示命令应该对什么进行操作。例如,当我们调用常见的 Unix 工具 mkdir(“创建目录”)来创建一个新目录时,我们使用类似于以下的命令调用它

mkdir tmp

其中 tmp 是要创建的新目录的名称。

正如我们所见,Bash 脚本本身也是可以运行的程序。因此,它们也可以接受参数。这些参数作为脚本的 *位置参数* 提供给程序。之前,我们了解到变量是一种参数。位置参数非常相似,但由数字而不是名称标识。例如,$1(或 ${1})扩展为脚本的第一个参数。因此,假设我们想创建一个名为 mkfile.sh 的简单脚本,它接受两个参数——一个文件名和一行文本——并使用指定的文本创建指定的 文件。我们可以按如下方式编写它

#!/bin/bash
echo "$2" > "$1"

(注意文件开头处的 #!/bin/bash 行;我们在 基本命令 中介绍了该行。当你运行此代码时,该行将保证它被 Bash shell 解释,即使你是从另一个程序运行或你的计算机具有非标准配置。)

通过运行 chmod +x mkfile.sh 使其可执行后,我们可以按如下方式运行它

./mkfile.sh file-to-create.txt 'line to put in file'

我们也可以通过使用 $@ 来一次性引用所有参数,它扩展为 *所有* 位置参数,按顺序排列。当用双引号括起来时,如 "$@",每个参数都成为一个独立的词语。(注意:$* 可能是更常见的替代方案,但 "$*" 成为单个词语,原始参数之间用空格隔开。"$@" 几乎总是比 $@$* 更可取,$@$* 允许包含空格的参数被拆分为多个词语,而 "$*" 将多个参数合并为单个词语。)这通常与内置命令 shift 结合使用非常有用,shift 会移除第一个位置参数,这样 $2 就变成 $1$3 就变成 $2,依此类推。例如,如果我们将 mkfile.sh 更改为以下内容

#!/bin/bash
file="$1" # save the first argument as "$file"
shift # drop the first argument from "$@"
echo "$@" > "$file" # write the remaining arguments to "$file"

然后我们可以按如下方式运行它

./mkfile.sh file-to-create.txt line to put in file

所有参数(文件名除外)将被写入文件。

位置参数的数量可以通过 $# 获取;例如,如果 $#3,则位置参数为 $1$2$3

注意,超过 $9 的位置参数需要使用花括号;如果你需要引用第十个参数,例如,你必须写 ${10} 而不是 $10。(后者将被解释为 ${1}0。)也就是说,通常不建议使用太多具有特定含义的参数,因为用户很难跟踪它们。如果你发现自己专门引用脚本的第十个参数,可能需要重新评估你的方法。

如果你有一些使用 Bash 或 Unix 工具的经验,你可能已经注意到,许多命令除了普通参数之外,还可以接受以连字符 - 开头的各种“选项”。例如,rm "$filename" 删除单个文件,而 rm -r "$dirname" 删除整个目录及其所有内容。(-r 代表“递归”:该命令“递归”地删除整个目录树。)这些选项实际上只是参数。在 rm "$filename" 中,只有一个参数("$filename"),而在 rm -r "$dirname" 中,有两个参数(-r"$dirname")。从某种意义上说,这些参数本身并没有什么特别之处,但这种选项表示法非常普遍,以至于被认为是标准;许多或大多数 Bash 内置命令都可以接受各种选项,稍后我们将看到支持选项作为 Bash 脚本参数的各种技术。

华夏公益教科书