shell 语法
1. 注释
# 这是一个单行注释
:<<EOF
这是多行注释
这是多行注释
这是多行注释
EOF
:<<'
这是多行注释
这是多行注释
这是多行注释
'
:<<!
这是多行注释
这是多行注释
这是多行注释
!
2. 变量
定义变量时,变量名不加美元符号,**NOTE: 变量名和等号之间不能有空格.**使用时变量前加美元符号.可加{}
分离边界
your_name="tom"
echo $your_name
myUrl="https://www.google.com"
readonly myUrl # 只读变量
unset variable_name # 删除变量
3. 字符串
字符串可用单引号或双引号,也可不用引号.
单引号限制:
- 单引号里的任何字符都会原样输出, 单引号字符串中的变量是无效的;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行), 但可成对出现, 作为字符串拼接使用。
双引号的优点:
- 双引号里可以有变量
- 双引号里可以出现转义字符
str='this is a string'
str="Hello, I know you are \"$your_name\"! \n"
echo ${#str} # 获取字符串长度
echo ${str:1:4} 提取子字符串
echo `expr index $str io` # 查找子字符串
4. 数组
bash支持一维数组(不支持多维数组), 并且没有限定数组的大小。
array_name=(value0 value1 value2 value3)
echo array_name[0]
echo array_name[@] #获取所有元素
length=${#array_name[@]} # 取得数组元素的个数
length=${#array_name[*]} # 取得数组元素的个数
lengthn=${#array_name[n]} # 取得数组单个元素的长度
5. 传递参数
执行 Shell 脚本时, 向脚本传递参数, 脚本内获取参数的格式为:$n。n 代表一个数字
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数。 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同, 但是使用时加引号, 并在引号中返回每个参数。 如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 |
$- | 显示Shell使用的当前选项, 与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误, 其他任何值表明有错误。 |
$* 与 $@ 区别:
- 相同点:都是引用所有参数。
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3, , 则 " * " 等价于 "1 2 3"(传递了一个参数), 而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
6. 运算符
Shell 和其他编程语言一样, 支持多种运算符, 包括:
- 算数运算符
- 关系运算符
- 布尔运算符
- 字符串运算符
- 文件测试运算符
a. 算术运算符
原生bash不支持简单的数学运算, 但是可以通过其他命令来实现, 例如 awk
和 expr
, expr
最常用。
两点注意:
- 表达式和运算符之间要有空格, 例如 2+2 是不对的, 必须写成 2 + 2, 这与我们熟悉的大多数编程语言不一样。
- 完整的表达式要被 **`` ** 包含, 注意这个字符不是常用的单引号, 在 Esc 键下边。
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | expr $a + $b 结果为 30。 |
- | 减法 | expr $a - $b 结果为 -10。 |
* | 乘法 | expr $a \* $b 结果为 200。 |
/ | 除法 | expr $b / $a 结果为 2。 |
% | 取余 | expr $b % $a 结果为 0。 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字, 相同则返回 true。 | [ $a == $b ] 返回 false。 |
!= | 不相等。用于比较两个数字, 不相同则返回 true。 | [ $a != $b ] 返回 true。 |
**注意:**条件表达式要放在方括号之间, 并且要有空格, 例如: [$a==$b] 是错误的, 必须写成 [ $a == $b ]。
b. 关系运算符
关系运算符只支持数字, 不支持字符串, 除非字符串的值是数字。
运算符 | 说明 | 举例 |
---|---|---|
-eq | 检测两个数是否相等, 相等返回 true。 | [ $a -eq $b ] 返回 false。 |
-ne | 检测两个数是否不相等, 不相等返回 true。 | [ $a -ne $b ] 返回 true。 |
-gt | 检测左边的数是否大于右边的, 如果是, 则返回 true。 | [ $a -gt $b ] 返回 false。 |
-lt | 检测左边的数是否小于右边的, 如果是, 则返回 true。 | [ $a -lt $b ] 返回 true。 |
-ge | 检测左边的数是否大于等于右边的, 如果是, 则返回 true。 | [ $a -ge $b ] 返回 false。 |
-le | 检测左边的数是否小于等于右边的, 如果是, 则返回 true。 | [ $a -le $b ] 返回 true。 |
c. 布尔运算符
运算符 | 说明 | 举例 |
---|---|---|
! | 非运算, 表达式为 true 则返回 false, 否则返回 true。 | [ ! false ] 返回 true。 |
-o | 或运算, 有一个表达式为 true 则返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 与运算, 两个表达式都为 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
d. 逻辑运算符
运算符 | 说明 | 举例 |
---|---|---|
&& | 逻辑的 AND | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
|| | 逻辑的 OR | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
e. 字符串运算符
运算符 | 说明 | 举例 |
---|---|---|
= | 检测两个字符串是否相等, 相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 检测两个字符串是否相等, 不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 检测字符串长度是否为0, 为0返回 true。 | [ -z $a ] 返回 false。 |
-n | 检测字符串长度是否不为 0, 不为 0 返回 true。 | [ -n "$a" ] 返回 true。 |
$ | 检测字符串是否为空, 不为空返回 true。 | [ $a ] 返回 true。 |
f. 文件测试运算符
操作符 | 说明 | 举例 |
---|---|---|
-b file | 检测文件是否是块设备文件, 如果是, 则返回 true。 | [ -b $file ] 返回 false。 |
-c file | 检测文件是否是字符设备文件, 如果是, 则返回 true。 | [ -c $file ] 返回 false。 |
-d file | 检测文件是否是目录, 如果是, 则返回 true。 | [ -d $file ] 返回 false。 |
-f file | 检测文件是否是普通文件(既不是目录, 也不是设备文件), 如果是, 则返回 true。 | [ -f $file ] 返回 true。 |
-g file | 检测文件是否设置了 SGID 位, 如果是, 则返回 true。 | [ -g $file ] 返回 false。 |
-k file | 检测文件是否设置了粘着位(Sticky Bit), 如果是, 则返回 true。 | [ -k $file ] 返回 false。 |
-p file | 检测文件是否是有名管道, 如果是, 则返回 true。 | [ -p $file ] 返回 false。 |
-u file | 检测文件是否设置了 SUID 位, 如果是, 则返回 true。 | [ -u $file ] 返回 false。 |
-r file | 检测文件是否可读, 如果是, 则返回 true。 | [ -r $file ] 返回 true。 |
-w file | 检测文件是否可写, 如果是, 则返回 true。 | [ -w $file ] 返回 true。 |
-x file | 检测文件是否可执行, 如果是, 则返回 true。 | [ -x $file ] 返回 true。 |
-s file | 检测文件是否为空(文件大小是否大于0), 不为空返回 true。 | [ -s $file ] 返回 true。 |
-e file | 检测文件(包括目录)是否存在, 如果是, 则返回 true。 | [ -e $file ] 返回 true。 |
其他检查符:
- -S: 判断某文件是否 socket。
- -L: 检测文件是否存在并且是一个符号链接。
7. 流程控制
流程控制可用break
和continue
控制循环
# if 语句
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
# for 循环
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
# 或
for var in item1 item2 ... itemN; do command1; command2… done;
# while 循环
while condition
do
command
done
# 无限循环
while :
do
command
done
# 或
while true
do
command
done
# 或
for (( ; ; ))
# until 循环
until condition
do
command
done
# case 多选择语句
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
8. 函数
-
函数返回值在调用该函数后通过
$?
来获得 -
调用函数时可以向其传递参数。在函数体内部, 通过 $n 的形式来获取参数的值, 例如, $1表示第一个参数, $2表示第二个参数
参数处理 | 说明 |
---|---|
$# | 传递到脚本或函数的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同, 但是使用时加引号, 并在引号中返回每个参数。 |
$- | 显示Shell使用的当前选项, 与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误, 其他任何值表明有错误 |
[ function ] funname [()] {
action;
[return int;]
}
9. 输入输出重定向
如果希望执行某个命令, 但又不希望在屏幕上显示输出结果, 那么可以将输出重定向到 /dev/null
如果希望屏蔽 stdout 和 stderr,可以这么写command > /dev/null 2>&1
.
**注意:**0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR.)这里的 2 和 > 之间不可以有空格, 2> 是一体的时候才表示错误输出。
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
需要注意的是文件描述符 0 通常是标准输入(STDIN), 1 是标准输出(STDOUT), 2 是标准错误输出(STDERR)。
10. 文件包含
. filename # 注意点号(.)和文件名中间有一空格
或
source filename
# 例
#使用 . 号来引用test1.sh 文件
. ./test1.sh
# 或者使用以下包含文件代码
# source ./test1.sh