Shell语法

Shell 是一个用 C 语言编写的帮助用户访问操作系统内核的程序,业界所说的 Shell 通常是指 Shell 脚本(Shell Script)。
大多数 Linux 系统默认的 Shell 解释器是 Bash(Bourne Again Shell),在一般情况下,人们并不区分 Bsh(Bourne Shell)和 Bash(Bourne Again Shell)。

1. Shell变量

[指定解释器]#!/bin/bash
[定义变量]变量名="变量值"
变量名和等号之间不能有空格,常量使用大写字母表示,变量名避免使用特殊符号和空格。
[使用变量]${变量名}
[删除变量]unset 变量名

[字符串变量]
string='This is a ${变量名}'
string="This is a ${变量名}"
单引号中的任何字符都会原样输出,双引号字符串中的变量会转换。
[特殊变量]
$0表示脚本名称,$1$2等表示传递给脚本的参数,$#表示传递给脚本的参数数量,$?表示上一个命令的退出状态。
[拼接字符串]string2="Link with ${string1}"
[获取字符串长度]${#string}
[提取子字符串]${string:1:4}
从字符串第 2 个字符开始截取 4 个字符
[查找子字符串]expr index "${string}" io
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个)

2. Shell数组

[定义数组]数组名=(值1 值2 ... 值n)
[定义关联数组]declare -A site=(["google"]="www.google.com" ["taobao"]="www.taobao.com")
[获取全部数组元素]${数组名[@]}
[获取数组长度]${#数组名[@]}
[获取单个数组元素长度]${#数组名[n]}
[获取数组全部键]${!数组名[@]}

3. Shell运算符

Bash原生不支持算术运算符,但是可以通过expr命令实现。
[算术运算符]`expr $a + $b - $c * $d / $e % $f`
表达式和运算符之间要有空格,完整的表达式要被反引号包含。
[关系运算符]
关系运算符只支持数字,不支持字符串,除非字符串的值是数字,而且必须放到方括号中,[] 两边必须是空格。
[ 是运算符,] 是它的结束符号。
-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。
[布尔运算符]
! 非运算,表达式为 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。
[逻辑运算符]
&& 逻辑的与 [[ $a -lt 100 && $b -gt 100 ]] 返回 false。
|| 逻辑的或 [[ $a -lt 100 || $b -gt 100 ]] 返回 true。
[字符串运算符]
= 检测两个字符串是否相等,相等返回 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。
[文件测试运算符]
-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。

4. Shell命令

[if else-if else语法]
if 必须有 fi 结尾,else-if 写作 elif,命令不能为空。

1
2
3
4
5
6
7
8
9
if 条件1
then
    命令1
elif 条件2 
then 
    命令2
else
    命令N
fi

[for循环]
1.第一种格式

1
2
3
4
for 变量 in 值1 值2 ... 值n
do
  命令
done

2.第二种格式

1
2
3
4
for  ((初始化表达式; 条件表达式; 更新循环变量表达式))
do
    命令
done

[while循环]

1
2
3
4
while ((条件))
do
    命令
done

[until 循环]

1
2
3
4
until ((终止条件))
do
    命令
done

[case多选择]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
case 变量 in
模式1)
    命令1
    命令2
    ...
    命令N
    ;;
模式2)
    命令1
    命令2
    ...
    命令N
    ;;
esac

[跳出循环]
break命令跳出所有循环(终止执行后面的所有循环),continue命令仅跳出当前循环。

5. Shell函数

函数在使用前必须定义,所以必须将函数放在脚本开始部分。
functionreturn 可以不加,如果不加 return,将以最后一条命令运行结果作为返回值。

1
2
3
4
5
function 函数()
{
    命令;
    return int;
}

6. Shell输入输出重定向

[将标准输入stdin重定向到文件]命令 < 文件
[将标准输入stdin以追加形式重定向到文件]命令 << 文件
[将标准输出stdout重定向到文件]命令 > 文件
[将标准输出stdout以追加形式重定向到文件]命令 >> 文件
[将标准输出stdout和标准错误stderr合并后重定向到文件]命令 > 文件 2>&1
[将标准输出stdout和标准错误stderr合并后以追加形式重定向到文件]命令 >> 文件 2>&1
[将标准输入stdin和标准输出stdout分别重定向到文件]命令 < 文件1 > 文件2
[屏蔽标准输出stdout和标准错误stderr]命令 > /dev/null 2>&1

7. Shell文件包含

Shell可以包含外部脚本,有2种语法格式。
. 文件名
点号 (.) 和文件名中间有一个空格。
source 文件名