$(...)
可以扩展成另一个命令的运行结果,该命令的所有输出都会作为返回值。
echo $(date)
Tue 30 Nov 2021 05:26:45 CST
上面例子中,$(date)
返回date
命令的运行结果。
单引号用于保留字符的字面含义,各种特殊字符在单引号里面,都会变为普通字符,比如星号(*
)、美元符号($
)、反斜杠(\
)等。
由于反斜杠在单引号里面变成了普通字符,所以如果单引号之中,还要使用单引号,不能使用转义,需要在外层的单引号前面加上一个美元符号($
),然后再对里层的单引号转义。
echo $'it\'s'
双引号比单引号宽松,大部分特殊字符在双引号里面,都会失去特殊含义,变成普通字符。
但是,三个特殊字符除外:美元符号($
)、反引号(`
)和反斜杠(\
)。这三个字符在双引号之中,依然有特殊含义,会被 Bash 自动扩展。
反斜杠在双引号之中保持特殊含义,用来转义。所以,可以使用反斜杠,在双引号之中插入双引号,或者插入反斜杠本身。
如果变量的值包含空格,则必须将值放在引号中。
var="hello world"
Bash 没有数据类型的概念,所有的变量值都是字符串。
如果变量值包含连续空格(或制表符和换行符),最好放在双引号里面读取。如果直接读取,Shell 会将连续空格合并成一个。只有放在双引号里面读取,才能保持原来的格式。
a="1 2 3"
echo "$a"
读取变量的时候,变量名也可以使用花括号{}
包围。这种写法可以用于变量名与其他字符连用的情况。事实上,读取变量的语法$foo
,可以看作是${foo}
的简写形式。
$?
: 上一个命令的退出码,用来判断上一个命令是否执行成功。返回值是0,表示上一个命令执行成功;如果不是零,表示上一个命令执行失败。
$0
: 当前 Shell 的名称(在命令行直接执行时)或者脚本名(在脚本中执行时)。
$#
: 脚本的参数数量。
$@
: 脚本的参数值,参数之间使用空格分隔。
$1
~ $9
: 对应脚本的第一个参数到第九个参数。
如果脚本的参数多于9个,那么第10个参数可以用${10}
的形式引用,以此类推。
getopts
命令用在脚本内部,可以解析复杂的脚本命令行参数,通常与while
循环一起使用,取出脚本所有的带有前置连词线(-
)的参数。
getopts optstring name
第一个参数optstring
是字符串,给出脚本所有的连词线参数。比如,某个脚本可以有三个配置项参数-l
、-h
、-a
,其中只有-a
可以带有参数值,而-l
和-h
是开关参数,那么getopts
的第一个参数写成lha:
,顺序不重要。注意,a
后面有一个冒号,表示该参数带有参数值,getopts
规定带有参数值的配置项参数,后面必须带有一个冒号(:
)。getopts
的第二个参数name
是一个变量名,用来保存当前取到的配置项参数,即l
、h
或a
。
while getopts 'lha:' OPTION; do
case "$OPTION" in
l)
echo "linuxconfig"
;;
h)
echo "h stands for h"
;;
a)
avalue="$OPTARG"
echo "The value provided is $OPTARG"
;;
?)
echo "script usage: $(basename $0) [-l] [-h] [-a somevalue]" >&2
exit 1
;;
esac
done
shift "$(($OPTIND - 1))"
上面例子中,while
循环不断执行getopts 'lha:' OPTION
命令,每次执行就会读取一个连词线参数(以及对应的参数值),然后进入循环体。变量OPTION
保存的是,当前处理的那一个连词线参数(即l
、h
或a
)。如果用户输入了没有指定的参数(比如-x
),那么OPTION
等于?
。循环体内使用case
判断,处理这四种不同的情况。
如果某个连词线参数带有参数值,比如-a foo
,那么处理a
参数的时候,环境变量$OPTARG
保存的就是参数值。
注意,只要遇到不带连词线的参数,getopts
就会执行失败,从而退出while
循环。比如,getopts
可以解析command -l foo
,但不可以解析command foo -l
。另外,多个连词线参数写在一起的形式,比如command -lh
,getopts
也可以正确处理。
变量$OPTIND
在getopts
开始执行前是1,然后每次执行就会加1。等到退出while
循环,就意味着连词线参数全部处理完毕。这时,$OPTIND - 1
就是已经处理的连词线参数个数,使用shift
命令将这些参数移除,保证后面的代码可以用$1
、$2
等处理命令的主参数。