脚本编程中的面向过程:顺序执行,选择执行,循环执行。在谈shell脚本之前我们来认识几个bash的特殊变量,并了解一下bash脚本的测试。
一、shell脚本中的特殊变量
$0 获取当前执行的shell脚本的文件名
$n 获取当前执行的shell脚本的第n个参数值,n=1..9
$* 获取当前shell的所有参数 “$1 $2 $3 …
$# 获取当前shell命令行中参数的总个数
$$ 获取当前shell的进程号(PID)
$! 执行上一个指令的PID
$? 获取执行的上一个指令的返回值(0 为成功, 非零为失败)
$@ 这个程序的所有参数 “$1″ “$2″ “$3″ “…”
二、shell脚本中的测试
1、条件测试
[expression] 命令行直接执行
[[ expression ]] 关键字的变量引用 判断执行
注:bash命令有执行状态返回值,而命令的执行结果与命令状态返回值截然不同的两个概念。其区别是命令执行后产生的结果,是否执行成功就有执行状态返回值判断 :echo$?返回值是0 执行成功,1-255 执行失败。
2、整数测试
expression :数值1 比较符号 数值2
-gt :大于 $A -gt $B --> A>B
-ge : 大于或等于 $A -ge $B --> A>=B
-eq : 等于 $A -eq $B --> A=B
-lt : 小于 $A -lt $B --> A<B
-le : 小于或等于 $A -le $B --> A<=B
-ne : 不等于 $A -ne $B --> A!=B
3、字符测试
expression :字符1 比较符号 字符2
> : 大于 < : 小于
== : 等于
=~ :判断左边的字符是否能够被右边的字符模式匹配
注:字符匹配命令 [[ $opt1 =~ $opt2 ]],一般做行首行尾锚定,$opt2不要加引号。
字符单目操作 :-z $STRING : 为空则为真,不空则为假
-n $STRING :为空则为假,不空则为真
4、组合测试
&&:与 ||:或 !:非
短路操作
与运算:1 && 1 =1 ,0 && {0,1} =0 ,1 && 0 =0
或运算:1 || {0 ,1} =1 , 0 || 1 =1 , 0 || 0 =0
5、文件测试
操作符 文件路径
-f:测试其是否为普通文件,即ls -l时文件类型为-的文件
-d: 测试其是否为目录文件,即ls -l时文件类型为d的文件
-e: 测试文件是否存在,存在为真,否则为假
-r: 测试文件对当前用户来说是否可读
-w: 测试文件对当前用户来说是否可写
-x: 测试文件对当前用户来说是否可执行
-s: 测试文件大小是否不空,不空则真,空则假
三、for循环结构
语法结构:
for 变量 in 列表 ;do
语句1 ;语句2 ;···
done
注:循环必须有退出条件,不然会成为死循环,此处列表即为限定条件。
四、while循环结构
语法结构:
while 测试条件 ;do
语句1;语句2;···
done
五、until循环结构
语法结构:
until 测试条件 ;do
语句1;语句2;···
done
六,for, while, until 三者的对比
三者如何退出循环:
for循环语句是遍历列表中的元素完成;
while循环语句是在循环体改变测试条件时,条件满足就循环,直到条件不再满足则退出循环;
until循环语句是在循环体改变测试条件时,条件不满足就循环,直到条件满足时则退出循环。
实战演练
1、写一个脚本
使用for循环统计/etc/fstab、/etc/rc.d/rc.sysinit、/etc/inittab文件中各自以#开头的行的行数和空白行数;
#!/bin/bash for File in /etc/fstab /etc/rc.d/rc.sysinit /etc/inittab; do echo "$File:" echo -e "\t#lines: `grep "^#" $File | wc -l`" echo -e "\tspace lines: `grep "^$" $File | wc -l`" done
2、写一个脚本
使用for循环,分别将user1、user2和user3加入到testgrp组中,以其为额外组;
#!/bin/bash groupadd testgrp for User in user1 user2 user3; do usermod -a -G testgrp $User done
3、写一个脚本
使用for循环,复制/etc/fstab、/etc/inittab和/etc/rc.d/init.d/functions文件至/tmp/目录中,并重命名为原有的名称之后加当前日期,如第一个文件为/tmp/fstab-2013-07-
#!/bin/bash for File in /etc/fstab /etc/inittab /etc/rc.d/init.d/functions; do Filename= basename $File cp $File /tmp/$Filename-`date +%F` done
4、写一个脚本
求200以内所有为3的整数倍的整数之和;
#!/bin/bash # Sum=0 for I in {1..200}; do if [ $[$I%3] -eq 0 ]; then Sum=$[$Sum+$I] fi done echo "Sum: $Sum."
5、写一个脚本
计算
100
以内所有奇数的和以及所有偶数的和;分别显示之;
#
5、写一个脚本
如果用户的ID号为偶数,则显示其名称和shell;对所有用户执行此操作;
#!/bin/bash while read LINE; do Uid=`echo $LINE | cut -d: -f3` if [ $[$Uid%2] -eq 0 ]; then echo $LINE | cut -d: -f1,7 fi done < /etc/passwd
6、写一个脚本
每隔5秒查看hadoop用户是否登录,如果登录,显示其登录并退出;否则,显示当前时间,并说明hadoop尚未登录:
#!/bin/bash who | grep "^hadoop" &> /dev/null RetVal=$? until [ $RetVal -eq 0 ]; do date sleep 5 who | grep "^hadoop" &> /dev/null RetVal=$? done echo "hadoop is here."
7、写一个脚本
使用for,while,until三个循环语句,计算100以内所有正整数的和;
fo语句
#!/bin/bash # Sum=0 for I in {1..100}; do let Sum=$[$Sum+$I] done echo $Sum
while语句
#!/bin/bash Sum=0 Count=1 while [ $Count -lt 100 ]; do let Sum+=$Count let Count++ done echo $Sum
until语句
#!/bin/bash Sum=0 Count=1 until [ $Count -gt 100 ]; do let Sum+=$Count let Count++ done echo $Sum
8、写一个脚本
使用while和until分别实现“转换用户输入的字符为大写,除了quit(遇见quit退出);”
while语句
#!/bin/bash read -p "A string: " String while [ "$String" != 'quit' ]; do echo $String | tr 'a-z' 'A-Z' read -p "Next [quit for quiting]: " String done
until语句
read -p "A string: " String until [ "$String" == 'quit' ]; do echo $String | tr 'a-z' 'A-Z' read -p "Next [quit for quiting]: " String done
9、写一个脚本
计算100以内所有偶数的和以及奇数的和;在一个循环中实现;
要求:分别使用for,while,until各自独立实现。
for语句
#!/bin/bash EvenSum=0 OddSum=0 for I in {1..100}; do if [ $[$I%2] -eq 0 ]; then EvenSum=$[$EvenSum+$I] else OddSum=$[$OddSum+$I] fi done echo "EvenSum is: $EvenSum. OddSum is: $OddSum."
while语句
#!/bin/bash EvenSum=0 OddSum=0 Count=0 while [ $Count -le 100 ]; do if [ $[$Count%2] -eq 0 ]; then let Sum+=$Count let count++ echo "EvenSum is:$Sum" else let Sum+=$Count echo "OddSum is:$Sum" fi done
until语句
#!/bin/bash EvenSum=0 OddSum=0 Count=0 until [ $Count -gt 100 ]; do if [ $[$Count%2] -eq 0 ]; then let Sum+=$Count let count++ echo "EvenSum is:$Sum" else let Sum+=$Count echo "OddSum is:$Sum" fi done