文身(tattoo),又叫刺青,或指文身者,是用带有颜色的针刺入皮肤底层而在皮肤上制造一些图案或字眼出来,通过刺破皮肤而在创口敷用颜料使身上带有永久性花纹。
变量
一、分类
环境变量
- 一般用大写字母表示,常见如:HOSTNAME、SHELL、HISTSIZE、USER、PATH、PWD、LANG、HOME、LOGNAME等。
- 相关操作
- 常看当前用户的环境变量:
env
或export
- 查看某个具体的环境变量:
echo $HISTSIZE
- 设置某个环境变量如$PATH:
PATH=/usr/local/someapp/bin:$PATH
- 设置环境变量的几种方式
- 直接修改
/etc/profile
,全部用户生效 - 修改
~/.bash_profile
,当前用户生效 - 使用
export
命令只对当前shell有效
- 直接修改
- 常看当前用户的环境变量:
普通变量,也称局部变量
- shell是弱类型的语言,其变量通常不用指定类型或初始化,默认字符串类型。
- 相关操作
- 定义变量并赋值
var=something
=
左右不可有空格,否则就变成了比较运算符了- 变量值的引号(单双引号)可有可无,shell无要求
- echo时双引号内部的变量可正常输出,单引号则不可
- 加上
export
命令则升级为环境变量,如export var=something
- 加上
readonly
命令则变为只读变量,如readonly var=something
- 此时无法修改变量值,也无法
unset
变量,只有重新登录shell才能继续操作此变量(其实已经没啥关系了,关了此shell变量生命周期就结束了)。
- 此时无法修改变量值,也无法
- 使用变量
$var
或${var}
- 销毁变量
unset var
- 不用加
$
符号
- 不用加
- 查看变量
set
或declare
,输出结果包含普通变量和环境变量 - 修改变量作用域
export
命令可使变量在当前shell及子shell中都可访问,退出登录或脚本执行结束后失效- 将变量加入到
/etc/profile
,此时每个用户登录后都可访问此变量source /etc/profile
可使加入的变量立即生效
- 取变量长度
- 字符串类型
${sharpvar}
,sharp代表#,md语法限制不能直接写 - 数组类型
${sharparr[@]}
或${sharparr[*]}
,sharp代表#,md语法限制不能直接写
- 字符串类型
- 定义变量并赋值
- 定义变量的三种形式
1
2
3var1=abc
var2='def'
var3="ghi"- 使用变量
echo $var1
或echo ${var2}
- 删除变量
unset var3
- 将命令的结果赋值给变量
1
2var4=`ls`
var4=$(ls)特殊变量
$?
:上一条代码执行的结果,0表示执行成功,否则为标准错误输出。$$
:当前shell的PID。$!
:最近一次执行的后台进程PID。$#
:统计参数的个数。$@
:所有参数。$*
:所有参数。$@
和$*
无双括号时等价,有双括号时差异明显- 编写
echo.sh
,代码见下方 - 运行
bash echo.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#!/bin/bash
echo ===================================
index=1
echo "没有被双引号括起来的情况:\$*,所有的参数被认为是各个独立的单词"
for arg in $*
do
echo "参数$index=$arg"
let "index+=1"
done
echo ===================================
index=1
echo "被双引号括起来的情况:\$*,所有的参数被认为是一个单词"
for arg in "$*"
do
echo "参数$index=$arg"
let "index+=1"
done
echo ===================================
index=1
echo "被双引号括起来的情况:\$@,所有的参数被认为是各个独立的单词"
for arg in "$@"
do
echo "参数$index=$arg"
let "index+=1"
done- 编写
$0
:脚本名。$n
:参数位置。
shell数组
定义数组
- 定义并初始化
arr=(1 2 3)
- 先定义再赋值
1
2
3arr[0]=1
arr[1]=2
arr[2]=3- 定义并初始化
取数组元素(数组元素的下标由0开始)
- 取某个元素
${arr[0]}
- 取所有元素
${arr[*]}或${arr[@]}
- 取某个元素
取数组长度
${ #arr[*]}
或${ #arr[@]}
二、进阶
${}
的特殊用法${var:-word}
:如果var为空或未定义则被赋值为word${var-word}
:大体同上,除了var设置了但为空时变量的结果将是null,而不是word
${var:+word}
:如果var为空或未定义则不做任何操作,否则被赋值为word${var:=word}
:如果var为空或未定义,则被赋值为word同时设置非空或已定义属性,否则为var自身${var:offset}
:取子串,从offset处的后一个字符开始取到最后一个字符${var:offset:length}
:取子串,从offset处的后一个字符开始取lenth长的子串
变量的切分、替换、提取
变量提取
- 使用通配符
- 使用下标
变量切分
变量替换
在函数中可使用local命令定义局部变量,使其不影响函数外的同名变量
- declare根据选项的不同,也可实现此功能
将算术表达式的结果赋值给一个变量要使用
let
命令将标准输入的结果赋值给一个变量
echo -n "Input:";read test
四大循环
循环(程序设计):是一种计算机科学运算领域的用语,也是一种常见的控制流程。
一、for
语法
- C语言风格
1
2
3
4for((exp1; exp2; exp3))
do
statements
done- Python语言风格,value_list的几种形式
- 直接给出具体的值,如
1 2 3 4
- 给出一个取值范围
{start..end}
,如{1..100} 使用命令的执行结果(反引号或$()都可以取得命令的执行结果),如`seq 1 10`或$(seq 1 10)
- 在markdown中使用双反引号可以让文章中的反引号正常显示
- 使用
shell
通配符(可以认为是一种精简化的正则表达式) - 使用特殊变量,如
$#
、$*
、$@
、$?
、$$
等。
- 直接给出具体的值,如
1
2
3
4for variable in value_list
do
statements
done
- demo
1 | #!/bin/bash |
- 方式一
1 | #!/bin/bash |
- 方式二
1 | #!/bin/bash |
- 方式三
1 | #!/bin/bash |
- 方式四
1 | #!/bin/bash |
二、seq命令(mac)
seq [-w] [-f format] [-s string] [-t string] [first [incr]] last
- -w, 填充0使得宽度相同
- -f, 以指定格式
- -s, 以指定字符串分割,默认(\n)
- -t, 以指定字符串结尾
demo
- seq -w 0 0.1 1
1
2
3
4
5
6
7
8
9
10
110.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0- seq -f “%3g” 99 100
1
299
100- seq -s# 1 10
1
1#2#3#4#5#6#7#8#9#10#%
- seq -t end 1 10
1
2
3
4
5
6
7
8
9
10
111
2
3
4
5
6
7
8
9
10
end
三、实战
文件内容
log/1.txt
1 | 1 |
文件内容
log/2.txt
1 | 6 |
循环读取单个文件内容
- 方式一
1 | #!/bin/bash |
- 方式二
1 | #!/bin/bash |
读取文件夹下所有文件内容
- 方式一
1 | #!/bin/bash |
- 方式二
1 | #!/bin/bash |
二、select
- 语法
1 | select var in value_list |
- 运行到
select
语句后,取值列表value_list
中的内容会以菜单的形式显示出来,用户输入菜单编号就表示选中了某个值,这个值就会赋给变量variable
,然后再执行循环体中的statements
。 - 其中value_list同for循环中Python风格中一致。
#?
用来提示用户输入菜单编号。^D
表示按下ctrl+d
组合键,作用是结束`select循环。
select是无限循环(死循环),输入空值或者输入无效的值都不会结束循环,只有遇到
break
语句或按下ctrl+d
组合键才能结束循环。
- demo
1 | echo "What is your favourite OS?" |
三、while
- while循环用于不断执行一系列命令,也用于从输入文件中读取数据,命令通常为测试条件,其语法格式为:
1 | while condition |
demo
- 正常循环判断
1
2
3
4
5
6
7
8#!/bin/bash
num=0
while [ $num -lt 5 ]
do
num=`expr $num + 1`
echo $num
done- 读取文件
1
2
3
4
5
6
7
8
9
10#!/bin/bash
while read line
do
Bashuser=`echo $line | awk -F: '{print $1,$NF}' | grep 'bash' | awk '{print $1}'`
if [ ! -z $Bashuser ]
then
echo "$Bashuser use bash shell."
fi
done < /etc/passwd
awk命令中,$NF代表的是最后一个字段,有关此命令的用法自行脑补
四、until
- 语法,意思是执行一系列命令
commands
直到条件condition
为true
时停止
1 | until condition |
- demo
1 | #!/bin/bash |
特殊变量和运算符
一、&
&
放在启动参数后面表示设置此进程为后台进程,进程切换到后台的时候把它称为job,切换到后台时会输出相关job信息
二、&&
command1 && command2
,表示&&
左边的命令command1
成功执行(即返回0)后,&&
右边的命令command2
才能够被执行。- 当
command1
执行不成功时,则command2
也不会被执行,即发生了短路作用
- 当
- demo:
cd ~/Desktop && touch 123.txt && mkdir test && cp 123.txt ./test/ && rm -f 123.txt
三、|
管道符号为一条竖线:”|”,是unix一个很强大的功能。
用法:
command 1 | command 2
,功能是把第一个命令command 1执行的结果作为command2的输入传给command 2demo:
ls -s | sort -nr
-s
是file size
-n
是按数字排序numeric-sort
-r
是反转reverse
该命令最终的效果是列出当前目录中的文件,并把结果作为sort命令参数,按数字递减顺序排序。
四、||
command1 || command2
,表示如果||
左边的命令command1
未执行成功,那么就执行||
右边的命令command2
。- 当
command1
执行成功时,则command2
不会被执行,同样发生了短路作用
- 当
- demo:
cd ~/Desktop && rm -f 123.txt && cat 123.txt &>/dev/null || echo "cat failed"
五、()
- 把几个命令合在一起执行
- 一条命令需要独占一个物理行,如果需要将多条命令放在同一行则命令之间使用命令分隔符
;
分隔。 - 执行的效果等同于多个独立的命令单独执行的效果。
()
表示在当前shell
中将多个命令作为一个整体执行。- 在执行前后都不会切换当前工作目录,也就是说命令组合都是在当前工作目录下被执行的(即便命令中有切换目录的命令)。
- demo:
cd ~/Desktop && mkdir ./test && ls -al;(cd ~/Desktop/test;ls -al);ls -al
- 可看到最终目录还是在
~/Desktop
- 可看到最终目录还是在
六、{}
- 把几个命令合在一起执行,作用同
()
- demo:
cd ~/Desktop && mkdir ./test && ls -al;{cd ~/Desktop/test;ls -al};ls -al
- 可看到最终目录切换到了
~/Desktop/test
- 可看到最终目录切换到了
七、特殊变量
$$
:Shell本身的PID(ProcessID)$!
:Shell最后运行的后台Process的PID$?
:显示最后命令的退出状态码,0表示没有错误,其他任何值表明有错误。- demo
1
2
3
4cd ~
echo $?
cd ~/Desktop/not_exists_dir
echo $?$-
:显示Shell使用的当前选项,与set命令功能相同。$*
:所有参数列表$@
:所有参数列表- 没有被双引号括起来的时候
$@
和$*
一样的,见到IFS(默认为空格)就划分字段 - 被双引号包起来的时候,
$*
将所有的参数认为是一个字段,$@以IFS来划分字段
- 没有被双引号括起来的时候
$#
:添加到Shell的参数个数$0
:Shell本身的文件名$1~$n
:添加到Shell的各参数值,$1
是第1参数、$2
是第2参数…$^
:所有的依赖文件,以空格分开(不包含重复的依赖文件)。$%
:如果目标是归档成员,则该变量表示目标的归档成员名称。例如:如果目标名称为mytarget.so(image.o)
,则$@
为mytarget.so
,而$%
为image.o
。demo
- 脚本
test.sh
- 脚本
1 | #!/bin/bash |
增加执行权限
sudo chmod +x test.sh
执行脚本
./test.sh a b c d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28脚本名称为:./test.sh
参数个数为:4
===================================
第1个参数为:a
第2个参数为:b
第3个参数为:c
第4个参数为:d
===================================
当前脚本进程ID为:13291
最后运行进程ID为:
===================================
直接输出$*: a b c d
直接输出$@:a b c d
===================================
被双引号括起来的情况:$*,所有的参数被认为是一个单词
参数1=a b c d
===================================
被双引号括起来的情况:$@,所有的参数被认为是各个独立的单词
参数1=a
参数2=b
参数3=c
参数4=d
===================================
没有被双引号括起来的情况:$*,所有的参数被认为是各个独立的单词
参数1=a
参数2=b
参数3=c
参数4=d
八、扩展
0
表示标准输入1
表示标准输出2
表示标准错误输出>
默认为标准输出重定向,与1>
相同2>&1
意思是把标准错误输出重定向到标准输出&>file
意思是把标准输出和标准错误输出都重定向到文件file
中
sleep和wait
一、sleep
二、wait
各种括号
一、$()
- 在
bash shell
中,$()
与反引号都可用做命令替换,用户可像在终端中输入命令一样,bash shell
会自动进行替换。 - demo
1 | version1=$(uname -r) |
反引号比$()通用,有的版本不支持$()写法
二、${}
${}
常用于变量替换(提取),一般情况下$var
与${var}
并没有什么不一样,但是用${}
会比较精确的界定变量名称的范围。使用场景
字符串提取
- 使用通配符
#
是去掉左边的字符串(从前往后),默认是最小匹配,##
是最大匹配%
是去掉右边的字符串(从后往前),默认是最小匹配,%%
是最大匹配
1
2
3
4
5
6
7#!/bin/bash
var=/dir1/dir2/dir3/dir4/a.b.txt
echo ${var#*/} #去掉第一个/及其左边的内容:dir1/dir2/dir3/dir4/a.b.txt
echo ${var##*/} #去掉最后一个/及其左边的内容:a.b.txt
echo ${var%.*} #去掉最后一个.及其右边的内容:/dir1/dir2/dir3/dir4/a.b
echo ${var%%.*} #去掉第一个.及其右边的内容:/dir1/dir2/dir3/dir4/a- 使用下标
1
2
3
4
5
6
7#!/bin/bash
var=/dir1/dir2/dir3/dir4/a.b.txt
echo ${var:0:5} #从下标0开始,取字符长度为5,得到:/dir1
echo ${var:5:5} #从下标5开始,取字符长度为5,得到:/dir2
echo ${var:5} #从下表5开始,取到字符串末尾,得到:/dir2/dir3/dir4/a.b.txt
echo ${var: -5} #从下表-5开始,取到字符串末尾,得到:/dir2/dir3/dir4/a.b.txt
echo ${var:(-5)} #从下表-5开始,取到字符串末尾,得到:/dir2/dir3/dir4/a.b.txt- 使用通配符
字符串替换
1
2
3
4#!/bin/bash
var=/dir1/dir2/dir3/dir4/a.b.txt
echo ${var/dir/directory} #将第一个dir替换为directory,得到:/directory1/dir2/dir3/dir4/a.b.txt
echo ${var//dir/directory} #将所有的dir替换为directory,得到:/directory1/directory2/directory3/directory4/a.b.txt针对变量不同状态赋值(没设定、空值、非空值)
${var:-string}
:若变量var
为空则用string
来替换${var:-string}
,否则变量var
不为空时,则用变量var的值来替换${var:-string}
。${var:=string}
:若var
为空时则用string
替换${var:=string}
的同时,把string
赋给变量var
。${var:=string}
很常用的一种用法是判断某个变量是否赋值,没有的话则给它赋上一个默认值。
${var:+string}
的替换规则和上面的相反,即只有当var
不是空的时候才替换成string
,若var
为空时则不替换或者说是替换成变量var
的值,即空值。${var:?string}
替换规则为:若变量var
不为空则用变量var
的值来替换${var:?string}
;若变量var
为空则把string
输出到标准错误中,并从脚本中退出。- 可利用此特性来检查是否设置了变量的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#!/bin/bash
var=/dir1/dir2/dir3/dir4/a.b.txt
echo ${var-test.txt}
echo ${file1-test.txt}
echo ${var:-test.txt}
echo ${file2:-test.txt}
echo ${var+test.txt}
echo ${file3+test.txt}
echo ${var:+test.txt}
echo ${file4:+test.txt}
echo ${var=test.txt}
echo ${file5=test.txt}
echo ${var:=test.txt}
echo ${file6:=test.txt}
echo ${var?test.txt}
echo ${file7?test.txt}
echo ${var:?test.txt}
echo ${file8:?test.txt}
取变量长度
- 取字符串长度
1
2
3#!/bin/bash
str=123456
echo ${#str}- 取数组元素个数
1
2
3
4#!/bin/bash
arr=(a b c)
echo ${#arr[@]}
echo ${#arr[*]}
三、[]和[[]]
[]完全等价于命令
test
,可用于测试表达式,常见如字符串比较,算术比较,文件等。- 文件检测
- 文件类检测
-e file
:文件是否存在(exist)-f file
:文件是否存在且为普通文件(file)-d file
:文件是否存在且为目录(directory)-b file
:文件是否存在且为块设备(block device)-c file
:文件是否存在且为字符设备(character device)-S file
:文件是否存在且为套接字文件(Socket)-p file
:文件是否存在且为命名管道文件FIFO(pipe)-L file
:文件是否存在且是一个链接文件(Link)
- 文件属性检测
-r file
:文件是否存在且当前用户可读-w file
:文件是否存在且当前用户可写-x file
:文件是否存在且当前用户可执行-u file
:文件是否存在且设置了SUID-g file
:文件是否存在且设置了SGID-k file
:文件是否存在且设置了sbit(sticky bit)-s file
:文件是否存在且大小大于0字节,即用于检测文件是否为非空白文件-N file
:文件是否存在,且自上次read后是否被modify
- 两个文件之间的比较
file1 -nt file2
:判断file1是否比file2新,即newer than
。file1 -ot file2
:判断file1是否比file2旧,即older than
file1 -ef file2
:判断file2与file2是否为同一文件,可用在判断hard link的判定上。主要意义在判定,两个文件是否均指向同一个分区上的同一个inode,即equal file
。
- 文件类检测
- 数值检测(支持正负整数,不支持浮点数)
int1 -eq int2
:两数值相等(equal)int1 -ne int2
:两数值不等(not equal)int1 -gt int2
:int1大于int2(greater than)int1 -lt int2
:int1小于int2(less than)int1 -ge int2
:int1大于等于int2(greater than or equal)int1 -le int2
:int1小于等于int2(less than or equal)
- 字符串检测
-z string
:判定字符串是否为空(zero),为空则返回true。string
或-n string
:判定字符串是否非空,为空则false。- 注:-n可省略
string1 = string2
或string1 == string2
:string1和string2是否相同,相同则返回true。==
和=
等价,但=
可移植性更好
str1 != str2
:str1是否不等于str2,不等则返回true。str1 > str2
:str1字母顺序是否大于str2,大于则返回true。str1 < str2
:str1字母顺序是否小于str2,小于则返回true。
- 逻辑检测
-a
或&&
:两表达式同时为true时才为true。-a
只能在test
或[]
中使用,&&
只能在[[]]
中使用
-o
或||
:两表达式任何一个true则为true。-o
只能在test
或[]
中使用,||
只能在[[]]
中使用
!
:对表达式取反()
:用于改变表达式的优先级,为了防止被shell解析,应该加上反斜线转义\( \)
- 文件检测
知识点
- 使用
[]
和[[]]
时必须有空格,这是强制要求的格式。 - test命令使用标准的数学比较符号来表示字符串的比较,而用文本符号来表示数值的比较。
- 大于符号或小于符号必须要转义,否则会被理解成重定向。
- 使用
四、(())及[[]]
(())
及[[]]
分别是[]
的针对数学比较表达式和字符串表达式的加强版。[[]]
中增加模式匹配特性。(())
不需要再将表达式里面的大小于符号转义,另新增了++、–、~、&、|、**、<<、>>、!、&&、||等运算。
五、参考
基本运算符
一、算术运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,如
awk
和expr
。知识点
- 表达式和运算符之间要有空格,这点很重要
=
作为算术运算符的赋值运算时不能有空格
- 完整的表达式要被反引号(``)包含
- 加(
+
)、减(-
)、乘(*
)、除(/
)、取余(%
)、赋值(=
)、相等(==
)、不相等(!=
)运算- 乘法运算注意转义字符的使用,如用
expr 2 \* 2
为正确写法,expr 2 * 2
则会报错 - 相等运算符(
==
)可用于比较字符串是否相等(作用和字符串运算符=
相同)
- 乘法运算注意转义字符的使用,如用
- 表达式和运算符之间要有空格,这点很重要
demo
1 | #!/bin/bash |
二、关系运算符
- 关系运算符只支持数字,不支持字符串(除非字符串的值是数字)。
- 算术运算符的
==
和字符串运算符的=
、!=
可以实现字符串相等、不相等比较
- 算术运算符的
- 相等(
-eq
)、不相等(-ne
)、大于(-gt
)、大于等于(-ge
)、小于(-lt
)、小于等于(-le
) - demo
1 | a=10 |
三、布尔运算符
- 布尔运算符需要使用单中括号
[]
- 非运算(
!
)、或运算(-o
)、与运算(-a
)
四、逻辑运算符
- 逻辑运算符和布尔运算符有点相似(从理解上),使用时需要用双中括号
[[]]
- 逻辑与(
&&
)、逻辑或(||
)
布尔运算符和逻辑运算符区别
- 使用上,布尔运算符使用单中括号
[]
,逻辑运算符使用双中括号[[]]
,不能混用 - 功能上,逻辑运算符会发生短路作用,布尔运算符则不会
- demo
1 | #!/bin/bash |
五、字符串运算符
- 字符串运算符可以实现对字符串的一些操作
=
:检测两个字符串是否相等,相等返回true。!=
:检测两个字符串是否相等,不相等返回true。-z
:检测字符串长度是否为0,为0返回true。-n
:检测字符串长度是否不为0,不为0返回true。$
:检测字符串是否为空,不为空返回true。
- demo
1 | #!/bin/bash |
六、文件测试运算符
- 文件测试运算符用于检测
Unix(类Unix)
文件的各种属性。-b file
:检测文件是否是块设备文件,如果是则返回true。-c file
:检测文件是否是字符设备文件,如果是则返回true。-d file
:检测文件是否是目录,如果是则返回true。-f file
:检测文件是否是普通文件(既不是目录也不是设备文件),如果是则返回true。-g file
:检测文件是否设置了SGID
位,如果是则返回true。-k file
:检测文件是否设置了粘着位(Sticky Bit
),如果是则返回true。-p file
:检测文件是否是有名管道,如果是则返回true。-u file
:检测文件是否设置了SUID
位,如果是则返回true。-r file
:检测文件是否可读,如果是则返回true。-w file
:检测文件是否可写,如果是则返回true。-x file
:检测文件是否可执行,如果是则返回true。-s file
:检测文件是否为空(文件大小是否大于0),不为空返回true。-e file
:检测文件(包括目录)是否存在,如果是则返回true。-S file
: 判断某文件是否socket,如果是则返回true。-L file
: 检测文件是否存在并且是一个符号链接,如果是则返回true。
demo
ls -al ./test.sh
,得到结果-rwxr-xr-x 1 yourname staff 12 5 31 01:09 ./test.sh
- 脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65#!/bin/bash
file="./test.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ]
then
echo "文件是个目录"
else
echo "文件不是个目录"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
if [ -S $file ]
then
echo "是socket文件"
else
echo "不是socket文件"
fi
if [ -L $file ]
then
echo "是链接文件"
else
echo "不是链接文件"
fi
七、总结
- 布尔运算符
-a
、-o
只能在test
或[]
中使用,逻辑运算符&&
、||
只能在[[]]
中使用。 - 注意区分
=
、!=
在不同脚本时所代表的运算符种类