1 控制结构
1.1 if...then
语法:
if test-command
then
commands
fi
加粗的字由程序员按需要替换。 特殊参数“$#”表示命令行参数的个数。
1.2 test内置命令
test命令的选项:
-d 检查文件是否存在以及该文件是否是目录文件
-e 检查文件是否存在
-f 检查文件是否存在以及该文件是否是普通文件(不是目录)
-r
检查文件是否存在以及该文件是否可读
-s
检查文件是否存在以及该文件是否大于0字节
-w
检查文件是否存在以及该文件是否可写
-x
检查文件是否存在以及该文件是否可执行
[]是test的同义词,可以把test的参数用方括号括起来,方括号两边必须有空白符。
1.3 if...then...else
语法:
if test-command
then
commands
else
commands
fi
可以把then和if放在同一行,并用分号“;”分隔。
1.4 if...then...elif
语法:
if test-command
then
commands
elif test-command
then
commands
else
fi
1.5 for...in
语法:
for loop-index in argument-list
do
commands
done
1.6 for
语法:
for loop-index
do
commands
done
loop-index接收命令行参数中的每个参数值,一次接收一个。
1.7 while
语法:
while test-command
do
commands
done
1.8 until
语法:
until test-command
do
commands
done
条件为真时退出循环。
1.9 break和continue
break跳出循环。continue结束本次循环,开始下一次循环。
1.10 case
语法:
case test-string in
pattern-1)
commands-1
;;
pattern-2)
commands-2
;;
pattern-3)
commands-3
;;
....
esac
1.11 select
语法:
select varname [in arg...]
do
commands
done
select将把用户选择的编号存在关键字REPLY中。如果忽略关键字in和参数列表,就用位置参数来取代arg项。
1.12 Here文档
例子:
grep -i "$1" <<+
Max June 22
...
+
第一行两个小于号(<<)说明后面有一个Here文档。小于号后面的一个或多个符号用于限定Here文档的内容-本例使用加号。
开始的分隔符必须紧挨着两个小于号,结束的分隔符必须独占一行。
2 文件描述符
进程打开文件时,Linux会把这个文件关联到一个数字(称为文件描述符)。
打开文件描述符:
exec n> outfile 打开一个输出文件outfile,并把它关联到文件描述符n
exec m< infile 打开一个输入文件infile,关联到文件描述符m。
exec n<&- 关闭文件描述符
3 参数和变量
3.1 数组变量
声明数组并赋值: name=(element1 element2 ...),例:NAMES=(max helen sam zach)
引用数组元素:${NAMES[2]},下标[*]和[@]都可以提取整个数组,但它们放在双引号中时,@会生成原始数组的一个副本,*将数组内容整合成一个元素。
运算符${#NAMES[*]}返回数组中元素的个数。
${#NAMES[1]}返回数组第二个元素的长度。
NAMES[1]=max可以改变数组第二个元素内容为max。
3.2 局部变量
变量默认情况下在声明它的进程中是局部变量,除非用export命令将变量导出为全局变量。
在函数中声明局部变量可以用typeset内置命令,如typeset count声明一个局部变量,变量名为count,函数局部变量只在函数内有效。
3.3 特殊参数
1 $$:PID编号。 $!:后台运行的最后一个进程的PID
2 $?:退出状态。存储最后一条命令的退出状态。非0意味着命令失败,0意味着命令成功。
使用exit内置命令和后面的一个数字可以指定shell脚本返回的退出状态。如果没有使用exit来终止脚本,则脚本的退出状态就是脚本最后一条命令的退出状态。
3.4 位置参数
1 $#:命令行参数的个数。保存除命令自身之外的参数个数。
2 $0:主调程序的名称。
3 $1-$n:命令行参数。当n超过9时,要用花括号引用,如第10个命令参数用${10}表示。
4 shift:左移命令行参数。向左移时,第一个参数($1)被丢弃,第2个参数变成第1个,依此类推。
被丢弃的参数不能再找回来。shift有一个可选的参数,指定移动的距离,默认是1.
5 set:初始化命令行参数。用一个或多个参数调用set命令时,set会把参数的值赋予位置参数,从$1开始。
6 $*和$@:表示所有命令行参数。加上双引号时,$*只能得到一个参数,而$@则生成一串参数,每个位置参数仍然是一个单独的参数。
3.5 扩展空变量和未赋值变量
表达式${name}中,如果name为空或没有赋值,则bash将name扩展成一个空字符串。
1 “:-”使用默认值
${name:-dafault} 如果
name为空或没有赋值,就用default替换name的值,但不会改变name变量本身,否则就使用name。
2 “:=”赋默认值
${name:=default}
如果
name为空或没有赋值,就将name赋值为default。
3 “:?”显示错误信息
${name:?message}
如果
name为空或没有赋值,就显示message,并终止脚本,以退出状态1返回。如果省略message,则显示默认的错误消息。
4 内置命令
4.1 type:显示命令的相关信息。
4.2 read:接受用户输入。
如果不想用一个变量来接收read的输入,则bash把输入放在一个名为REPLY的变量中。
选项-p可以提示用户,如:read -p "Please enter:" cmd 输入的变量存在cmd变量中。
4.3 exec:执行命令
exec有两个主要作用:1 使用它运行命令时不用创建新进程。 2 使用它重定向来自shell脚本内部的文件描述符。
1 使用exec运行命令
语法: exec command arguments
由于使用exec时不返回控制权,因此在shell脚本中把它作为最后一条命令。
2 使用exec重定向输入和输出
exec < infile 把标准输入重定向为一个名为infile的文件
exec > outfile 2> errfile 把标准输出和标准错误分别重定向为outfile和errfile文件。
/dev/tty是用户的工作屏幕的假名,exec > /dev/tty将标准输出重定向到用户屏幕。exec < /dev/tty将标准输入重定向到键盘。
4.4 trap:捕获信号
语法:trap ['commands'] [signal]。可选项command指出了当脚本在捕获到signal信号时执行的命令,signal可以是信号名称或编号,如INT或2.如果没有commands命令,trap命令会把trap重置为初始条件,一般就是从脚本退出。如果不想退出脚本但又不想运行任何命令,可以给commands指定一个空字符串。
可以利用命令 kill -l、trap -l来查看所有信号的名称列表。
4.5 kill:终止进程
语法:kill [-signal] PID 其中signal是信号的名称或编号,PID是要接收信号的进程标识符。可以用%n的形式指定一个作业编号来替代PID。如果省略signal,kill就发出一个TERM(软件终止信号,编号15)信号。
4.6 getopts:解析选项
语法:getopts optstring varname [arg...] 其中,optstring是合法的字母选项列表,varname变量保存每次接收的选项的值,arg是即将处理的可选参数列表。若不存在arg参数,getopts就处理命令行参数。getopts使用变量OPTIND(选项索引)和 OPTARG(选项参数)来跟踪存储与选项相关的值。
5 表达式
5.1 算术表达式
方式一: let "value=value*10 + new" value和new必须包含整数,不需要再变量前加$符号。
方式二: ((value=value*10 + new))
let的每个参数被看作一个独立的表达式,所以可以在一行上给多个变量赋值: let "count=count+1" value=value*10+new 或者 ((count=count+1, value=value*10+new))
算术求值与算术扩展不同,算术扩展的语法是$((expression)),计算表达式并取代$((expression));算术求值的语法为 let expresstion或((expression)),计算表达式,并返回一个状态码。利用算术求值可以进行逻辑比较或者赋值运算。
5.2 逻辑表达式
语法:[[ expresstion ]]
其中
expresstion
是一个逻辑表达式。注意在符号“[[”和“]]”两边必须用空格或者命令终结符隔开,同时在每个变量前面加上美元符号。
例:if [[ 30 < $age && $age < 60 ]]; then 或者 if [[ 30 -lt $age && $age -lt 60 ]]; then
5.3 字符串模式匹配
4个字符串匹配运算符如下:
#:删除最小匹配前缀
##:删除最大匹配前缀
%:删除最小匹配后缀
%%: 删除最大匹配后缀
运算符的语法:${varname op pattern},op就是4个运算符中的一个。pattern是一个匹配类型,它和生成文件名的模式很相似。
例如:source=/usr/local/src/prog.c ${source#/*/}为local/src/prog.c
5.4 运算符
bash中的算术运算符采用和c语言相同的语法、运算符优先级以及表达式的相互关系。可以用括号改变求值的顺序。
管道运算符的优先级比所有的运算符都要高。