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 脚本参数的各种技术。