「Shell」 Shell中的特殊符号


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命令,表达式必须紧凑,不能含有空格,但是如果非要在表达式中加空格,则必须将整个表达式用引号引起来。

文章作者: Hyggge
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Hyggge !
  目录