Bourne Shell 脚本/变量扩展
在 环境 模块中,我们介绍了环境变量的概念,作为存储小片段数据的一种通用方式。在本模块中,我们将深入探讨如何使用这些变量:'变量扩展'、'参数替换'或简称'替换'。
使用变量被称为替换的原因是,Shell 实际上用每个变量的值替换对任何变量的引用。这在评估命令行时完成,这意味着变量替换是在命令实际执行之前进行的。
使用变量的最简单方法是我们已经见过的,在变量名前面加上一个 '$'。例如
当然,一旦替换完成,结果仍然只是变量中的文本。该文本的解释仍然由执行的任何程序完成。例如
基本变量扩展已经相当灵活。您可以按照上面描述的方式使用它,但也可以使用变量来创建更长的字符串。例如,如果您想将应用程序的日志目录设置为主目录中的 "log" 目录,您可以这样填写设置
$HOME/log
如果您要更频繁地使用该设置,您可能想要创建自己的变量,例如
LOGDIR=$HOME/log
当然,如果您想要为不同的程序创建特定的日志子目录,那么 Wyxliz 应用程序的日志将进入目录
$LOGDIR/Wyxliz/
Bourne Shell 有许多不同的变量替换语法,每种语法都有其自己的含义和用途。在本节中,我们将研究这些语法。
我们已经详细讨论过基本变量替换:您定义一个变量,在其前面加上一个 '$',Shell 会用变量的值替换它。到目前为止,您可能已经厌倦了听到它。
但是我们还没有谈到基本变量替换中您可能会遇到的一个情况。考虑以下情况
那么这里出了什么问题?好吧,显然 Shell 没有为 ANIMAL 变量替换任何东西,但为什么?因为加上 's' 后,Shell 认为我们要求的是不存在的 ANIMALs 变量。但这怎么会这样?我们之前在字符串中间使用过变量(如 '/home/ANIMAL/logs')。但是 's' 不是 '/':'s' 可以是变量名的一部分,因此 Shell 无法区分它们。在您必须明确地将变量与其他文本分隔开的情况下,可以使用大括号
两种情况(有括号和没有括号)都算作基本变量替换,规则完全相同。只需记住不要在大括号和变量名之间留任何空格。
由于变量可以为空,您通常会在脚本中编写代码来检查强制变量是否真的有值。但在可选变量的情况下,通常不进行检查,而是使用一个默认值来处理变量未定义的情况。这种情况实际上非常普遍,因此 Bourne Shell 为其定义了一种特殊语法:破折号。由于破折号对 Shell 也有其他含义,因此您必须将其与大括号结合起来 - 最终的结果看起来像这样
而 default 是在 varname 未定义时使用的值
同样,不要在大括号和其余文本之间留任何空格。使用此语法的步骤如下
将其与以下代码进行比较
没有冒号,变量将仅在未定义时被替换
$ VAR=value EMPTY_VAR=
$ echo ${VAR:-empty}, ${EMPTY_VAR:-empty}, ${ABSENCE_VAR:-empty}
value, empty, empty
$ echo ${VAR-empty}, ${EMPTY_VAR-empty}, ${ABSENCE_VAR-empty}
value, , empty
作为默认值的扩展,存在一种语法不仅提供默认值,而且同时将默认值赋给未设置的变量。它看起来像这样
而 default 是在 varname 未定义时使用的和赋值的值
像往常一样,避免在大括号之间留空格。以下示例演示了此语法的工作原理
$ echo $NEWVAR
$ echo ${NEWVAR:=newval}
newval
$ echo $NEWVAR
newval
没有冒号,变量将仅在未定义时被赋值
$ echo $NEWVAR
$ EMPTY_VAR=
$ unset ABSENCE_VAR
$ echo ${EMPTY_VAR:=empty}, ${ABSENCE_VAR:=empty}
empty, empty
$ echo ${EMPTY_VAR}, ${ABSENCE_VAR}
empty, empty
$ EMPTY_VAR=
$ unset ABSENCE_VAR
$ echo ${EMPTY_VAR=empty}, ${ABSENCE_VAR=empty}
, empty
$ echo ${EMPTY_VAR}, ${ABSENCE_VAR}
, empty
这种替换有点像快速测试来查看变量是否已定义(通常这就是它的用途)。它有点像默认值语法的反向,看起来像这样
而 substitute 是在 varname 已定义时使用的值
如果变量已定义,则此语法将返回替换值。乍一看这似乎违反直觉,尤其是当您问如果变量未定义会返回什么 - 并了解到返回值为空时。以下是一个示例
$ echo ${NEWVAR:+newval}
$ NEWVAR=oldval
$ echo ${NEWVAR:+newval}
newval
那么,这种符号有什么用呢?好吧,它经常用于必须检查大量变量是否已设置的脚本中。在这种情况下,变量具有值意味着已激活某个选项,因此您感兴趣的是知道变量是否具有值,而不是该值是什么。它看起来有点像这样(伪代码,这在 Shell 中实际不起作用)
没有冒号,变量即使为空也会被替换
$ VAR=value EMPTY_VAR=
$ echo ${VAR:+newvalue}, ${EMPTY_VAR:+newvalue}, ${ABSENCE_VAR:+newvalue}
newvalue, ,
$ echo ${VAR+newvalue}, ${EMPTY_VAR+newvalue}, ${ABSENCE_VAR+newvalue}
newvalue, newvalue,
这种最终的语法就像一个调试检查,用来检查变量是否被设置。它看起来像这样
如果varname没有定义,则会打印message。
使用这种语法,如果变量已定义,一切正常。否则,将打印消息,并且命令或脚本以非零退出状态退出。或者,如果没有消息,则会打印文本“参数为空或未设置”。
您可以使用这种语法来检查脚本的必需变量是否已设置,并在未设置时打印错误消息。
$ echo ${SOMEVAR:?has not been set}
-sh: SOMEVAR: has not been set
$ echo ${SOMEVAR:?}
-sh: SOMEVAR: parameter null or not set
使用冒号,变量也会被检查是否为空。
$ EMPTY_VAR=
$ echo ${EMPTY_VAR:?has not been set or empty}
-sh: EMPTY_VAR: has not been set or empty
$ echo ${ABSENCE_VAR:?has not been set or empty}
-sh: ABSENCE_VAR: has not been set or empty
$ echo ${EMPTY_VAR?has not been set or empty}
$ echo ${ABSENCE_VAR?has not been set or empty}
-sh: ABSENCE_VAR: has not been set or empty