条件测试
条件判断语句
循环语句
shell函数
调试方法


条件测试和条件判断:
条件测试
整数测试
字符串测试
文件测试
组合测试条件
算术运算
if条件判断
case条件判断


条件测试:
if/then结构用来判断命令列表的退出状态码是否为0(因为在UNIX惯例, 0表示“成功”), 如果成功的话, 那么就执行接下来的一个或多个命令
条件测试通常不会产生标准输出;其返回值为测试结果:“0”表示“真”(True),“1”表示“假”(False)
常可用来判断“字符串”、“整数”、“文件”等
条件测试使用方式:
test expression 或
[□expression□] 或
[[□expression□]]
说明:
“test”和”[“ 均为命令,”[[”是关键字
上面的形式中的□为空格,必须


整数测试:
-eq
等于   [ "$a" -eq "$b" ]
-ne
不等于   [ "$a" -ne "$b" ]
-gt
大于   [ "$a" -gt "$b" ]
-ge
大于等于   [ "$a" -ge "$b" ]
-lt
小于   [ "$a" -lt "$b" ]
-le
小于等于   [ "$a" -le "$b" ]
, =, , =
此些需要在双括号 (()) 中才能使用
(( “$A” > “$B“ ))


字符串测试:
=
等于      [ "$a" = "$b" ]
!=
不等于      [ "$a" != "$b" ]
<
小于 [ “$a” \ < $b ] ,转义
>
大于 [[ “$a” > “$b” ]]
-z
字符串为 "null", 意思就是字符串长度为零
-n
字符串不为 "null"

使用后两种方式测试时,建议字符串用双引号引起来
[…]中的大于号和小于号需要转义,[[…]]则不需要


文件测试:
-f file
测试文件是否为普通文件
-d dir
存在且为一个目录时为真
-h -L file
测试文件是否为符号链接
-r
文件是否具有可读权限 ( 正在运行此测试命令的用户 )
-w
文件是否具有可写权限 ( 正在运行此测试命令的用户 )
-x
文件是否具有可执行权限 ( 正在运行此测试命令的用户 )
-e
判断文件是否存在
-s
判断文件大小是否为 0 ,不为 0 时返回真
f1 -nt f2
文件 f1 比文件 f2
f1 -ot f2
文件 f1 比文件 f2
f1 -ef f2
文件 f1 和文件 f2 是相同文件的硬链接
" " -- 反转上边所有测试的结果


组合测试条件:

-a 逻辑与
exp1 -a exp2 如果表达式exp1和exp2都为真的话,则结果为真。
-o 逻辑或
exp1 -o exp2 如果表达式exp1和exp2中至少有一个为真的话,那么结果为真。

这与&&和||操作符很类似
&&和||如果用来组合测试条件,只能用于[[…]]中,而一般 -a 和 –o 是用在[…]中或test语句中


shell的算术运算:
shell也可以进行简单的算术运算
格式如下:
$((expression)) 或
$[ expression ]
也可以使用let命令来进行变量的算术操作,如:let SUM=3+5, let “A += 2”
条件测试中的算术测试使用方式
结果为非零的时候, 将会返回退出状态码0;反之,返回状态码1


if条件判断结构:
if [ condition1-true]
then
command

fi
if [ condition2-true]
then
command

else
command

fi

if/then/fi都是独立的语句,若放在同一行,需要用分号分隔。

退出和退出状态码:
exit 被用来结束一个脚本, 就像在C语言中一样;它也返回一个值, 并且这个值会传递给脚本的父进程, 父进程会使用这个值做下一步的处理
成功的命令返回0, 而不成功的命令返回非零值, 非零值通常都被解释成一个错误码
脚本中的函数和脚本本身也会返回退出状态码 ,在脚本中,“ exit nnn”命令将会把 nnn退出码传递给shell( nnn必须是十进制数, 范围必须是0 - 255)
当一个脚本退出, $?保存了脚本的退出状态码, 这个退出状态码也就是脚本中最后一个执行命令的退出状态码
有些退出状态码被系统保留,有其特殊的含义

一个嵌套的if例子:





case语句:

case "$variable" in

"$condition1")
command...
;;

"$condition2")
command...
;;

esac


case的作用和多个if/then/else语句的作用相同, 是它们的简化结构, 特别适用于创建菜单
每句测试行, 都以右小括号)来结尾
每个条件判断语句块都以一对分号结尾
case块以esac (case的反向拼写)结尾


case例子:
小计算器,求两个数的加、减、乘、除;
./caculator.sh 4 + 5 #如果在命令行输入* ,需要转义




read命令:

从stdin中“读取”一个变量的值, 也即是和键盘进行交互来取得变量的值
格式:read [options] VAR1 VAR2 VAR3 …
常用选项:
-s 安静模式,输入的字符不显示
-p “String” 读取输入之前打印出后边的提示符
-t TIMEOUT 读取到数据前等待的时间,超时则停止
read命令也可以从重定向的文件中“读取”变量的值
如果文件中的内容超过一行, 那么只有第一行被分配到这个变量中
如果read命令的参数个数超过一个, 那么每个变量都会从文件中取得一个分配的字符串作为变量的值, 这些字符串都是以定义的空白字符来进行分隔的


例子:对所选文件以指定方式压缩




循环结构:
for循环
while循环
until循环
break、continue


for循环:
格式:

for arg in [list]
do
command

done

在循环的每次执行中, arg将顺序的访问list中列出的变量
list中的参数允许包含通配符
如果do和for想在同一行中出现, 那么在它们之间需要添加一个分号
可以将一个变量放在for循环的[list]位置上
在一个for循环中忽略in [list]部分的话, 将会使循环操作$@ -- 从命令行传递给脚本的位置参数
也可以使用命令替换 来产生for循环的[list]

例子:判断某目录下所有文件的类型





while循环:

格式:
while [conditions]
do
command

done

while循环更适合在循环次数未知的情况下使用
while在条件满足时执行循环
如果想把do和条件判断放到同一行上的话,中间需要一个分号
while循环可以通过(())来使用C风格的语法,如
((SUM=0))
((I=1))
while ((I <= 100))
do
((SUM += $I))

例子:从文件中读取每一行显示并统计行数





until循环:
格式:
until [conditions]
do
command

done


until在条件不满足时执行循环
until循环的条件判断在循环的顶部,这与某些语言的使用方法不同
如果想把do和条件判断放在同一行里, 需要使用分号

例子:在某redhat登录时给他发一封邮件


who命令可用来显示当前系统上登录的用户
v  
break & continue:
break命令用来跳出循环
continue命令只会跳过本次循环, 忽略本次循环剩余的代码, 进入循环的下一次迭代
break命令可以带一个参数. 一个不带参数的break命令只能退出最内层的循环, 而break N可以退出N层循环
例子:计算100以内偶数的和



函数:
function F_NAME {
command

}
函数定义必须在第一次调用函数之前完成,没有像C中函数"声明"的方法
“{”可以写在下一行
只需要简单的调用函数名, 函数就会被调用或触发
对于左边的声明方法,括号不能省略
函数可以处理传递给它的参数, 并且能返回它的退出状态码给脚本, 以便后续处理
函数返回一个值, 被称为退出状态码;退出状态码可以由return命令明确指定, 也可以由函数中最后一条命令的退出状态码来指定

bash程序的调试 :
调用bash的形式是:
bash -选择项shell程序文件名
几个常用的选择项是:
 -n:读入脚本,不执行,只检查语法错误
 -u:置换时把未声明的变量看作出错
 -v:在运行脚本之前先显示出每一个命令
 -x:打印出每个命令执行的结果, 但只使用缩写形式