Shell中有一系列诸如
${ }
,$[ ]
,$( )
,[[ ]]
这样的特殊符号,它们长相相似但用法却大相径庭,非常容易混淆。笔者在写Shell脚本时也经常将它们的用法弄混,因此特地整理在此,以便日后查阅。
$ 的用法
在写Shell脚本时,我们经常会定义一些变量。如果想要获取变量的值,则需要使用
${变量名}
。当然,$变量名
也是可以的,不过${}能够明确变量的边界,可以防止在字符串拼接时出现问题。
#!/bin/bash
var1=100
var2=200
echo ${var1}
echo $var2
------------------------ 运行结果 ------------------------
100
200
$( ) 和 ` `
$( )
和<code>
`
`</code>
都用做命令替换,能够返回某个命令的运行结果。当我们使用这两个符号运行某个命令时,实际上就是在当前Shell中fork出一个子Shell,并在子Shell中运行命令,并将结果返回给父Shell。
#!/bin/bash
echo `date`
echo $(date)
------------------------ 运行结果 ------------------------
2022年 07月 25日 星期一 22:06:03 CST
2022年 07月 25日 星期一 22:06:03 CST
( ) 和 { }
( )
和
{ }
作用相似,都是将括号中的所有命令作为一个命令组来顺序执行(括号中不同命令之间需要用分号
;
来分隔)。但是,二者又有下面几点区别——
( )
内部各个命令和左右括号之间不必有空格,而{ }
中第一个命令和左括号之间必须要有一个空格。( )
最后一条指令后面可以没有;
,而{ }
最后一条指令后面必须有;
( )
中的命令会在新开的一个Shell中运行,而{ }
的命令是在当前Shell中运行。
#!/bin/bash
(echo -n "Hello"; echo -n " Hyggge"; echo -e "\n";)
{ echo -n "Hello"; echo -n "World"; echo -e "\n";}
------------------------ 运行结果 ------------------------
Hello Hyggge
Hello World
[ ] 和 test
[ ]
和
test
命令用法相同,都是用来测试“某个条件是否成立”。如果成立则返回0(真),否则返回非0值(假)。test
命令的语法格式为
test <条件>
,若使用 [ ]
则应该写做
[<条件>]
。两者通常需要结合
if
一起使用
“测试条件”中支持以下几种表示判断或者关系的运算符——
- 测试文件: -e, -f, -d, -r, -w, -x等
- 字符串比较: =, !=, -z, -n, $
- 数值比较: ==, !=, -eq, -ne, -gt, -lt, -ge, -le
- 布尔运算: !, -o, -a
#!/bin/bash
a=100
b=200
if test $a -lt $b;then
echo "a < b!"
fi
if [ $b -gt $a ]; then
echo "b > a!"
fi
------------------------ 运行结果 ------------------------
a < b!
b > a!
需要注意的是,在使用
[ ]
时,左右括号和条件之间必须留有空格。
[[ ]] 的用法
[[ ]]
可以看做增强版的
[ ]
,除了可以使用上面提到的运算符,还可以使用
&&
, ||
, <
,
>
,更加符合我们使用C语言的习惯。
#!/bin/bash
if [[ 1 < 2 && 4 > 3 ]];then
echo "yes!"
fi
------------------------ 运行结果 ------------------------
yes!
$(( )), $[ ], let 和 expr
$(( ))
, $[ ]
, let
,
expr
都可以用于数值的运算。
$(( ))
的括号中可以使用任何符合C语言语法的表达式,如果括号中的是数值运算表达式,则返回运算结果;如果括号中是逻辑判断表达式,则返回1或者0(1表示真,0表示假,与退出状态码相反)。#!/bin/bash a=100 b=200 c=$((a + b)) # c=$(($a + $b)) echo $c echo $((a + b == c)) ------------------------ 运行结果 ------------------------ 300 1
如果
(( ))
单独使用,则只能用于括号内表达式的运算,而不能将表达式的运算结果返回。此外,(( ))
也经常在for
循环中使用,用于循环控制,类似C语言。#!/bin/bash a=100 b=200 ((c = a + b)) echo $c sum = 0 for ((i = 0; i < 100; i++));do ((sum += i)) done echo $sum ------------------------ 运行结果 ------------------------ 300 4950
$[ ]
用法和$(( ))
基本相同,同样支持任何符合C语言语法的表达式。expr
命令只能用于"数值运算"(例如expr b + c
),不能用作"变量赋值"(例如expr a = b + c
)。该命令除了能够进行数学运算时,还可与进行字符串比较、字符串匹配、字符串提取、字符串长度计算等功能。#!/bin/bash a=100 b=200 c=`expr $a + $b` echo $c ------------------------ 运行结果 ------------------------ 300
let
命令可以和(( ))
进行互换,同样只能进行表达式的运算,而不能将运算结果返回。#!/bin/bash a=100 b=200 let c=a+b echo $c let "c = a - b" echo $c ------------------------ 运行结果 ------------------------ 300 -100
需要特别注意以下几点:
- 在使用
$(( ))
、$[ ]
和let
时,直接通过变量名即可获得变量所代表的值,不需要使用${ }
。- 在使用
$(( ))
和$[ ]
时,括号中表达式的任意位置都可以有空格;对于expr
命令,运算符两边必须有空格;对于let
命令,表达式必须紧凑,不能含有空格,但是如果非要在表达式中加空格,则必须将整个表达式用引号引起来。