<code>Bash编程之循环&函数</code>
<code>一、bash循环(</code><code>for</code><code>,</code><code>while</code><code>,until)</code>
<code>二、测试脚本</code>
<code>三、多分支</code><code>if</code>
<code>四、</code><code>case</code><code>语句的语法格式</code>
<code>五、function函数</code>
<code>六、变量作用域</code>
<code>七、函数递归</code>
一、bash循环(for,while,until)
1.bash脚本编程
顺序执行
选择执行
循环执行
for,while,until,
进入条件:
for :列表元素非空
while :条件测试结果为“真”
until:条件测试结果为“假”
退出条件:
for:列表元素为空
while:条件测试结果为“假”
until:条件测试结果为“真”
2.循环控制语句:
while CONDATION1 ; do
CMD1
...
if CONDATION2;then
continue //结束本次循环
fi
CMDn
...
done
示例:求100以内所有偶数之和
3.创建循环体;
while true ;do
循环体
退出方式:某个测试条件满足时,让循环体执行break命令
break:直接跳出循环
continue:直接进入下一次循环
sleep 数字[时间单位] //默认是s,d:天,h:小时
4.while循环的特殊用法(遍历文件的行)
while read VAR; don
done < /path/to/somefile
依次读取/path/from/somefile文件中的每一行,且将某赋值给VAR变量
示例:脚本5
5.for循环的特殊用法
for ((控制变量初始化;条件判断表达式;控制var的修正语句))
循环体
done
控制变量初始化,仅在循环代码开始运行时执行一次
控制变量的修正语句;每轮循环结束会先进行控制变量修正运算,而后在根据判断条件判断
二、测试脚本
脚本1:求even:偶数,odd:奇数,100以内之和
<code> </code><code>#!/bin/bash</code>
<code> </code><code>declare -i evensum=0 /</code>
<code> </code><code>declare -i i=0</code>
<code> </code><code>while</code> <code>[ $i -le 100 ] ; </code><code>do</code>
<code> </code><code>let</code> <code>i++ </code><code>//前面不能用let $i++</code>
<code> </code><code>if</code> <code>[ $[$i%2] -eq 0 ] ;then </code><code>//此处只能使用[ ] 进行引用</code>
<code> </code><code>let</code> <code>evensum+=$i</code>
<code> </code><code>else</code>
<code> </code><code>continue</code>
<code> </code><code>fi</code>
<code> </code><code>done</code>
<code> </code><code>echo </code><code>"Even sum is $evensum"</code>
//求所有奇数之和2500
<code> </code><code>declare -i evensum=0</code>
<code> </code>
<code> </code><code>while</code> <code>[ $i -lt 100 ] ; </code><code>do</code> <code>//必须是小于100,否则会出错</code>
<code> </code><code>let</code> <code>i++</code>
<code> </code><code>if</code> <code>[ $[$i%2] -eq 1 ] ;then</code>
<code> </code><code>let</code> <code>evensum+=$i</code>
<code> </code><code>else</code>
<code> </code><code>continue</code>
<code> </code><code>fi</code>
脚本2:求和,break方式实现
<code> </code><code>#!/bin/bashk</code>
<code> </code><code>declare -i oddsum=0</code>
<code> </code><code>declare -i i=1</code>
<code> </code><code>while</code> <code>true</code><code>; </code><code>do</code>
<code> </code><code>let</code> <code>oddsum+=$i</code>
<code> </code><code>let</code> <code>i+=2</code>
<code> </code><code>if</code> <code>[ $i -gt 100 ];then</code>
<code> </code><code>echo $oddsum</code>
<code> </code><code>break</code>
脚本3:每个三s获取已经登录的用户信息,如果wolf用户已经登录,则记录于日志中,并退出
<code> </code><code>if</code> <code>who |grep wolf &> /dev/</code><code>null</code> <code>; then</code>
<code> </code><code>sleep 3</code>
<code> </code><code>echo </code><code>"$(date +%F-%H-%M) wolf loggin..."</code> <code>>> /tmp/userlog.log</code>
脚本4:util实现脚本3
<code> </code><code>until who | grep </code><code>"wolf"</code> <code>&> /dev/</code><code>null</code> <code>; </code><code>do</code>
<code> </code><code>sleep 3</code>
脚本5:当前os上id号为偶数的用户及其shell
<code> </code><code>declare -i userid</code>
<code> </code><code>while</code> <code>read i ;</code><code>do</code>
<code> </code><code>userid=`echo $i | cut -d: -f3`</code>
<code> </code><code>//注:同上userid=$(echo $i | cut -d: -f3)</code>
<code> </code><code>if</code> <code>[ $[$userid%2] -eq 0 ] ;then</code>
<code> </code><code>echo $i | cut -d: -f1,7</code>
<code> </code><code>done < /etc/passwd</code>
<code> </code><code>//另一种实现方式,while循环 </code>
<code> </code><code>userid=$(echo $i | cut -d: -f3)</code>
<code> </code><code>username=$(echo $i | cut -d: -f1)</code>
<code> </code><code>usershell=$(echo $i | cut -d: -f7)</code>
<code> </code><code>if</code> <code>[ $[$userid%2] -eq 0 ] ;then</code>
<code> </code><code>echo </code><code>"$username $userid $usershell"</code>
<code> </code><code>done < /etc/passwd</code>
脚本6:for的特殊用法
<code> </code><code>declare -i sum=0</code>
<code> </code><code>for</code> <code>((i=1;i<=100;i++));</code><code>do</code>
<code> </code><code>let</code> <code>sum+=$i</code>
<code> </code><code>echo </code><code>"Sum: is .$sum"</code>
脚本7;使用for的特殊用法,打印99表
<code> </code><code>#</code>
<code> </code><code>for</code> <code>((i=1;i<=9;i++));</code><code>do</code>
<code> </code><code>for</code> <code>((j=1;j<=i;j++));</code><code>do</code>
<code> </code><code>echo -e -n </code><code>"${i}*${j}=$[$i*$j]\t"</code>
<code> </code><code>done</code>
<code> </code><code>echo </code><code>//这个echo用于换行,因为前面不换行了</code>
三、多分支if
多分支if
if condation1;then
..
elif
...
else
fi
单分支if
示例1:显示一个菜单给用户
要求:
1.提示用户给出自己的选择
2.正确的选择,则给出相应的信息,否则提示,用户重新选择
<code> </code><code>cat << EOF</code>
<code> </code><code>cpu) display cpu information</code>
<code> </code><code>mem) display memory information</code>
<code> </code><code>disk) display disks information</code>
<code> </code><code>quit) quit</code>
<code> </code><code>===============================</code>
<code> </code><code>EOF</code>
<code> </code><code>read -p </code><code>"Enter your choice: "</code> <code>opt</code>
<code> </code><code>while</code> <code>[ </code><code>"$opt"</code> <code>!= </code><code>"cpu"</code> <code>-a </code><code>"$opt"</code> <code>!= </code><code>"mem"</code> <code>-a </code><code>"$opt"</code> <code>!= </code><code>"disk"</code> <code>-a </code><code>"$opt"</code> <code>!= </code><code>"disk"</code> <code>-a "$</code>
<code> </code><code>opt</code><code>" != "</code><code>quit</code><code>" ] ;do read -p "</code><code>Enter your choice: " opt</code>
<code> </code><code>if</code> <code>[ </code><code>"$opt"</code> <code>== </code><code>"cpu"</code> <code>] ;then</code>
<code> </code><code>lscpu</code>
<code> </code><code>elif [ </code><code>"$opt"</code> <code>== </code><code>"mem"</code> <code>] ;then</code>
<code> </code><code>free -m</code>
<code> </code><code>elif [ </code><code>"$opt"</code> <code>== </code><code>"disk"</code> <code>] ;then</code>
<code> </code><code>fdisk -l /dev/sd[a-z] </code>
<code> </code><code>else</code>
<code> </code><code>echo </code><code>"quit"</code>
<code> </code><code>exit 0</code>
<code> </code><code>fi</code>
四、case语句的语法格式
case $VAR in //仅仅支持glob风格的通配符
PAT1)
;; //双分号结尾
PAT2)
;; //
...
*)
;;
esac
注意:
case支持glob风格的通配符
*:任意长度的任意字符
?:任意单个字符
[]:范围内的
a|b :a或者b
case实现示例
<code> </code><code>case</code> <code>$opt </code><code>in</code>
<code> </code><code>cpu) </code><code>//不用加“ ”</code>
<code> </code><code>;; </code><code>//最后要加 ;;</code>
<code> </code><code>disk)</code>
<code> </code><code>fdisk -l /dev/sd[a-z]</code>
<code> </code><code>;;</code>
<code> </code><code>mem)</code>
<code> </code><code>*)</code>
<code> </code><code>exit 0 ;;</code>
<code> </code><code>esac</code>
五、function函数
过程式编程:代码重用
模块化编程
结构化编程
把一段独立功能的代码当做一个整体,并为之一个名字;命名的代码段,此即为函数
注意:定义函数的代码段不会自动执行,在调用时执行,所谓调用函数,在代码中给定函数名即可
函数名出现的任何位置,在代码执行时,都会被自动替换为函数代码
语法一:
function f_name () { //function和f_name之间有空格
...函数体...
}
语法二:
f_name() { //f_name() 中间没有空格
...函数体...
函数的生命周期:每次被调用时,返回时终止
其状态返回结果:函数体中运行的最后一条命令的状态结果;
自定义状态返回值:需要使用:return
return [0-255]
0:成功
1-255:失败
脚本使用:exit #作为其返回值
示例:脚本4
注意:在函数中,不能使用$1,$2,...因为具有特殊的意义
因为函数也可以接受参数,
$1,$2调用的是,传递给函数的参数,而不是脚本的参数
函数返回值
函数的执行结果返回值;
(1)使用echo或printf命令进行输出
printf不会自动换行,相当于echo -n
(2)函数体中调用的命令的执行结果
函数的退出状态码
1.默认取决于函数最后执行的那一条命令
2.自定义的方法,return
函数可以接受参数
传递参数给函数
1.在函数体中,可以使用$1,$2,...引用传递给函数的参数;
$*和$@调用所有参数,
$#引用参数个数
2.在调用函数时,在函数名后以空白字符分隔给定参数列表即可,例如:a b c d
六、变量作用域
局部变量:作用域是函数的声明周期
定义:locale VARIABLE=VALUE
本地变量:作用域是运行脚本的shell的生命周期;作用范围是当前shell程序
a=VALUE //
全局变量:
环境变量:
全局变量和局部变量对比:
<code> </code><code>#!/bin/bash</code>
<code> </code><code>name=tom</code>
<code> </code><code>setname() {</code>
<code> </code><code>local name=jerry</code>
<code> </code><code>echo </code><code>"Function name:$name"</code>
<code> </code><code>}</code>
<code> </code><code>setname</code>
<code> </code><code>echo </code><code>"Shell: $name"</code>
<code> </code><code>[root@localhost ~]# bash 2.sh</code>
<code> </code><code>Function name:jerry</code>
<code> </code><code>Shell: tom</code>
七、函数递归 //自己调用自己
函数间接或者直接就调用自身
10!=10*9!=10*9*8!=...
<code>#!/bin/bash</code>
<code>fact() {</code>
<code> </code><code>if</code> <code>[ $1 -eq 0 -o $1 -eq 1 ] ;then </code><code>//[ $1 -eq 0 ] || [ $1 -eq 1 ] 这样也可以</code>
<code> </code><code>echo $1</code>
<code> </code><code>echo $[$1*$(fact $[$1-1])]</code>
<code>}</code>
<code>fact $1</code>
<code>fab() {</code>
<code> </code><code>if</code> <code>[ $1 -eq 1 ] ;then</code>
<code> </code><code>echo -n </code><code>"1 "</code>
<code> </code><code>elif [ $1 -eq 2 ] ;then</code>
<code> </code><code>echo -n </code><code>"1 "</code>
<code> </code><code>echo -n </code><code>"$[$(fab $[$1-1]+$(fab $[$1-2])]"</code>
<code>} </code>
<code>for</code> <code>i </code><code>in</code> <code>$(seq 1 $1) ;</code><code>do</code>
<code> </code><code>fab $i</code>
<code>done</code>
<code>echo</code>
服务启动服务框架
$lockfile,值/var/lock/subsys/SCRIPT_NAME
1.可以接受的参数start,stop,restart,status四个参数
2.如果参数非此四个,则显示帮助后退出
3.start,创建lockfile,并显示启动:stop,则创建lockfile,并显示停止;restart,则先删除此文件,再创建此文件,而后显示重启完成,;
statue根据lockfile是否存在,显示running/stopped
注:务必使用case语句
<code>#</code>
<code># chkconfig: - 50 50</code>
<code># description test_service_script</code>
<code>prog=$(basename $0)</code>
<code>lockfile=/</code><code>var</code><code>/</code><code>lock</code><code>/subsys/$prog</code>
<code>case</code> <code>$1 </code><code>in</code>
<code>start)</code>
<code> </code><code>if</code> <code>[ -f $lockfile ] ;then</code>
<code> </code><code>echo </code><code>"$prog is running yet."</code>
<code> </code><code>touch $lockfile </code>
<code> </code><code>[ $? -eq 0 ] && echo </code><code>"Start $prog finished.."</code>
<code> </code><code>;;</code>
<code>stop)</code>
<code> </code><code>rm -f $lockfile</code>
<code> </code><code>[ $? -eq 0 ] && echo </code><code>"$prog stopped.."</code>
<code> </code><code>echo </code><code>"$prog is not running.."</code>
<code>restart)</code>
<code> </code><code>if</code> <code>[ -f $lockfile ] ; then </code>
<code> </code><code>touch $lockfile</code>
<code> </code><code>echo </code><code>"$prog restart finished.."</code>
<code> </code><code>echo </code><code>"$prog start finished.."</code>
<code>status)</code>
<code> </code><code>echo </code><code>"$prog is running.."</code>
<code> </code><code>echo </code><code>"$prog is stopped.."</code>
<code>*)</code>
<code> </code><code>echo </code><code>"Usage: $prog {start|stop|resatrt|status}"</code>
<code>esac </code>
<code> </code><code>cp service /etc/init.d/service</code>
<code> </code><code>chmod +w /etc/init.d/service</code>
<code> </code><code>chkconfig --add service</code>
<code> </code><code>service service start</code>
八、function脚本
1.给定一个用户名,获取其id和shell
<code> </code><code>userinfo() {</code>
<code> </code><code>if</code> <code>id </code><code>"$username"</code> <code>&> /dev/</code><code>null</code> <code>;then </code>
<code> </code><code>grep </code><code>"$username"</code> <code>/etc/passwd | cut -d: -f3,7</code>
<code> </code><code>else</code>
<code> </code><code>echo </code><code>"No $username such user.."</code>
<code> </code><code>}</code>
<code> </code><code>username=$1</code>
<code> </code><code>userinfo </code><code>//调用该函数,可以调用多次</code>
<code> </code><code>username=$2</code>
<code> </code><code>userinfo</code>
2.升级版
<code> </code><code># chkconfig: - 50 50</code>
<code> </code><code># description test_service_script</code>
<code> </code><code>prog=$(basename $0)</code>
<code> </code><code>lockfile=/</code><code>var</code><code>/</code><code>lock</code><code>/subsys/$prog</code>
<code> </code><code>start() {</code>
<code> </code><code>if</code> <code>[ -f $lockfile ] ;then</code>
<code> </code><code>echo </code><code>"$prog is running yet."</code>
<code> </code><code>touch $lockfile </code>
<code> </code><code>[ $? -eq 0 ] && echo </code><code>"Start $prog finished.."</code>
<code> </code><code>stop() {</code>
<code> </code><code>rm -f $lockfile</code>
<code> </code><code>[ $? -eq 0 ] && echo </code><code>"$prog stopped.."</code>
<code> </code><code>echo </code><code>"$prog is not running.."</code>
<code> </code><code>restart() {</code>
<code> </code><code>if</code> <code>[ -f $lockfile ] ; then </code>
<code> </code><code>touch $lockfile</code>
<code> </code><code>echo </code><code>"$prog restart finished.."</code>
<code> </code><code>echo </code><code>"$prog start finished.."</code>
<code> </code><code>status() {</code>
<code> </code><code>echo </code><code>"$prog is running.."</code>
<code> </code><code>echo </code><code>"$prog is stopped.."</code>
<code> </code><code>usage() {</code>
<code> </code><code>echo </code><code>"Usage: $prog {start|stop|resatrt|status}"</code>
<code> </code><code>case</code> <code>$1 </code><code>in</code>
<code> </code><code>start)</code>
<code> </code><code>start ;;</code>
<code> </code><code>stop)</code>
<code> </code><code>stop ;;</code>
<code> </code><code>restart)</code>
<code> </code><code>restart;;</code>
<code> </code><code>status)</code>
<code> </code><code>status;;</code>
<code> </code><code>usage;;</code>
3.添加10个用户
添加用户的功能用函数实现,用户名作为参数传递给函数
<code># 5: user is exists</code>
<code>adduser() {</code>
<code> </code><code>if</code> <code>id $1 &> /dev/</code><code>null</code><code>; then</code>
<code> </code><code>return</code> <code>5</code>
<code> </code><code>useradd $1</code>
<code> </code><code>retval=$?</code>
<code> </code><code>return</code> <code>$retval </code>
<code>for</code> <code>i </code><code>in</code> <code>{1..10} ;</code><code>do</code>
<code> </code><code>adduser ${1}$i </code>
<code> </code><code>a=$? </code><code>//$?不要直接引用,如果需要多次引用的话,进行赋值变量</code>
<code> </code><code>if</code> <code>[ $a -eq 0 ] ;then</code>
<code> </code><code>echo </code><code>"useradd succeed..."</code>
<code> </code><code>elif [ $a -eq 5 ] ;then</code>
<code> </code><code>echo </code><code>"user ${1}$i is exists ,useradd failure."</code>
<code> </code><code>echo </code><code>"Unknown errors.."</code>
<code></code>
本文转自MT_IT51CTO博客,原文链接:http://blog.51cto.com/hmtk520/1979188,如需转载请自行联系原作者