1. 引号

单引号和双引号用于变量值出现空格时将字符用引号括起来。 二者的主要区别在于 ,

被单引号括起来的字符都是普通字符 , 就算特殊字符也不再有特殊含义 ;

被双引号括起来的字符中 ,、\和反引号是拥有特殊含义的。代表引用变量的值 , 而反引号代表引用命令。

1.1 单引号

单引号(full quoting [single quote])。

强引用。单引号括住的内容 , 被视为单一字符串 , 引号内的禁止变量扩展 , 所有字符均作为字符本身处理(除单引号本身之外) , 单引号必须成对出现。

[root@centos7 ~]# echo '$PATH'
$PATH

1.2 双引号

双引号(partial quoting [double quote])。

弱引用部分引用。双引号包围的内容可以允许变量扩展 , 也允许转义字符的存在。如果字符串内出现双引号本身 , 需要转义 , 因此不一定双引号是成对的。

[root@centos7 ~]# echo "$PATH"
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

1.3 反引号

反引号(Command substitution[backquotes])。

命令替换。这个反引号包围的为命令 , 可以执行包围的命令 , 并将执行的结果赋值给变量。

[root@centos7 ~]# date
Wed Aug 25 17:22:29 CST 2021
[root@centos7 ~]# echo `date`
Wed Aug 25 17:22:34 CST 2021
#先运行反引号中的date命令,只有通过echo将date命令运行的结果打印出来

: $(...) 的作用与反引号一样 , 也是命令替换

2. 括号

2.1. 小括号

  1. 命令组(Command group)。由一组圆括号括起来的命令是命令组 , 命令组中的命令是在子shell(subshell)中执行。因为是在子shell内运行 , 因此在括号外面是没有办法获取括号内变量的值 , 但反过来 , 命令组内是可以获取到外面的值 , 这点有点像局部变量和全局变量的关系 , 在实作中 , 如果碰到要cd到子目录操作 , 并在操作完成后要返回到当前目录的时候 , 可以考虑使用subshell来处理 ;

  2. 用于数组的初始化。

2.2. 中括号

单方括号最常见用于逻辑判断中 , 另外它还可以作为数组的下标 , 以及在正则中表示一段范围

shell脚本中用于条件判断 :

if [ 1 > 2] then
   ...
fi

也可以作为数组下标

# echo ${lnmp[1]}
​
nginx

在正则中使用 , 表示一段范围。 [0-9] 表示数子0-9都行

其他关于中括号的用法如下。

$[...]

词表达表示整数扩展(integer expansion)。

在方括号里面执行整数表达式。例 :

a=3
b=7
echo $[$a+$b]
echo $[$a*$b]
##返回是10和21
echo [$a+$b] 这里返回值为[3+7]

2.3. 大括号

  • {}。代码块功能。

    小括号和大括号同样可以实现这个功能,主要区别在于 :

    • () 执行一串命令时 , 需要重新开启一个子Shell来执行。{} 执行一串命令时 , 在当前Shell中执行。

    • (){} 都是把一串命令放在括号里面 , 并且命令之间用;隔开。

    • () 最后一条命令可以不用分号。{} 最后一条命令要用分号。

    • {} 的第一条命令和左括号之间必须有一个空格。

    • (){} 中括号里面的某条命令的重定向只影响该命令 , 但括号外的重定向则会影响到括号里的所有命令。

    • 其实在执行一串命令时 , 如果使用的是小括号 , 则这串命令所做的修改只在子Shell 中生效 , 一旦命令执行结束 . 回到父Shell 中 , 这个修改就会丟失 ; 而如果使用的是大括号 , 则此串命令直接在父 Shell 中执行 ,命令执行结束后 ,修改依然会生效。

  • {a..z..2} :a表示开始字符,z表示结束字符,2表示步长,即每隔两个字母打印一次。这种方式适合数字字母

    Bash version 3时添加了这种花括号扩展的扩展 , 可以使用{A..Z}表示A-Z的所有字符列表 , 这种方式的扩展Mitchell测试了一下 , 好像仅适用于A-Z, a-z , 还有数字{最小..最大}的这种方式扩展。

    [root@centos7 ~]# echo {A..a}
    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [  ] ^ _ ` a

    这个排序是按照ASCII码的大小值来输出的。所以按照上述所示的输出可以看出

    [root@centos7 ~]# echo {A..[}
    {A..[}

    这种方式同时也只适合字母数字。

    [root@centos7 ~]# echo {-10..1}
    -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1
  • {x,y,z}

    在命令中可以用这种扩展来扩展参数列表 , 命令将会依照列表中的括号分隔开的模式进行匹配扩展。注意的一点是, 这花括号扩展中不能有空格存在 , 如果确实有必要空格 ,则必须被转义或者使用引号来引用。

    [root@centos7 ~]# echo {a,b,c}-{\ d," e",' f'}
    a- d a- e a- f b- d b- e b- f c- d c- e c- f

其实上面两种参数列表的方式更适合形成某些有规律的字符串,或者用于匹配某些有规律的字符串。这种形式也是通配符的一种。

[root@centos7 ~]# echo string{00..11..2}file{a,b,c}
string00filea string00fileb string00filec string02filea string02fileb string02filec string04filea string04fileb string04filec string06filea string06fileb string06filec string08filea string08fileb string08filec string10filea string10fileb string10filec
​
[root@localhost mnt]# touch file{1,10}
[root@localhost mnt]# ls
file1  file10
[root@localhost mnt]# touch file{1..10}
[root@localhost mnt]# ls
file1  file10  file2  file3  file4  file5  file6  file7  file8  file9
[root@localhost mnt]# touch file{1..10..2}
[root@localhost mnt]# ls
file1  file3  file5  file7  file9
[root@localhost mnt]# touch file{0000..10..2}
[root@localhost mnt]# ls
file0000  file0002  file0004  file0006  file0008  file0010
[root@localhost mnt]# echo {A..z}
A B C D E F G H I J K L M N O P Q
R S T U V W X Y Z [  ] ^ _ ` a b c 
d e f g h i j k l m n o p q r s t 
u v w x y z
[root@localhost mnt]# echo {A..z..2}{1..3}
A1 A2 A3 C1 C2 C3 E1 E2 E3 G1 G2 G3 I1 I2
I3 K1 K2 K3 M1 M2 M3 O1 O2 O3 Q1 Q2 Q3 S1
S2 S3 U1 U2 U3 W1 W2 W3 Y1 Y2 Y3 [1 [2 [3 
]1 ]2 ]3 _1 _2 _3 a1 a2 a3 c1 c2 c3 e1 e2 
e3 g1 g2 g3 i1 i2 i3 k1 k2 k3 m1 m2 m3 o1
o2 o3 q1 q2 q3 s1 s2 s3 u1 u2 u3 w1 w2 w3 
y1 y2 y3

3. 其他

3.1 点号

点号(dot command [period])。

  1. 相当于bash内建命令source , 如:

    #!/bin/bash
    . data-file
    #包含data-file;
  2. 作为文件名的一部分 , 在文件名的开头 , 表示该文件为隐藏文件 , ls一般不显示出来(ls -a可以显示);

  3. 作为目录名 , 一个点代表当前目录 , 两个点号代表上层目录(当前目录的父目录)。注意 , 两个以上的点不出现 , 除非你用引号(单/双)包围作为点号字符本身 ;

  4. 正则表达式中 , 点号表示任意一个字符。

3.2 冒号

冒号(null command [colon])。

空命令。 这个命令什么都不做 , 但是有返回值 , 返回值为0(即 : true)。

  1. 可做while死循环的条件 ;

  2. if分支中作为占位符(即某一分支什么都不做的时候) ;

  3. 放在必须要有两元操作的地方作为分隔符。

    : ${username=`whoami`}
  4. 在参数替换中为字符串变量赋值 , 在重定向操作(>)中 , 把一个文件长度截断为0(:>>这样用的时候 , 目标存在则什么都不做) , 这个只能在普通文件中使用 , 不能在管道 ,符号链接和其他特殊文件中使用;

  5. 甚至你可以用来注释( #后的内容不会被检查 , 但:后的内容会被检查, 如果有语句如果出现语法错误 , 则会报错);

  6. 你也可以作为域分隔符, 比如环境变量$PATH中 , 或者passwd中 , 都有冒号的作为域分隔符的存在

  7. 你也可以将冒号作为函数名 , 不过这个会将冒号的本来意义转变(如果你不小心作为函数名 , 你可以使用unset -f : 来取消function的定义)。


参考链接

Linux Shell基础 单引号、双引号、反引号、小括号和大括号 - lizhouwei - 博客园 (cnblogs.com)

Bash 中的特殊字符大全【转】 - 都市烟火 - 博客园 (cnblogs.com)


熊熊