加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

15、bash编程、case、函数

发布时间:2020-12-15 20:04:48 所属栏目:安全 来源:网络整理
导读:1、bash脚本编程: 选择执行:if单分支、if双分支、if多分支;case语句 2、case语句: 语法格式: case $VARIABLE in //$VARIABLE是变量引用,in是关键字 PAT1)//模式1 分支1 ;; //以双分号结束分支1语句 PAT2) 分支2 ;; ... *)//所有都不匹配,为*,类似els

1、bash脚本编程:

选择执行:if单分支、if双分支、if多分支;case语句


2、case语句:

语法格式:

case $VARIABLE in //$VARIABLE是变量引用,in是关键字

PAT1)//模式1

分支1

;; //以双分号结束分支1语句

PAT2)

分支2

;;

...

*)//所有都不匹配,为*,类似else

分支n

;;

esca

注意:①、每个case中的模式语句必须以双分号结尾,这里的双分号可以单独成行,也可以放在每个分支的最后一条语句后面,PAT仅支持golb风格的通配符(*、?、[ ] 、[^ ])

②、case语句仅适用于一个变量与多个值分别做模式匹配时适用。


3、示例:显示一个如下菜单给用户

cpu) display cpu information

mem)display mem information

disk)display disk information

*) quit

要求:提示用户给出自己的选择

正确的选择则给出相应的信息,否则,则提示重新选择正确的选项。

if语句实现:

[root@localhost sh]# cat men.sh

#!/bin/bash

cat << EOF

cpu) display cpu information

mem)display mem information

disk)display disk information

*) quit

EOF


read -p "enter your choice:" choice


while [ "$choice" != "cpu" -a "$choice" != "mem" -a "$choice" != "disk" -a "$choice" != "*" ];do

echo "please make sure your choice"

read -p "enter your choice again:" choice

done


if [ "$choice" == "cpu" ];then

lscpu

elif [ "$choice" == "mem" ];then

free

elif [ "$choice" == "disk" ];then

fdisk -l /dev/[hs]d[a-z]

else

echo "quit"

exit 4

fi

[root@localhost sh]#

case语句实现:

[root@localhost sh]# cat case.sh

#!/bin/bash

cat << EOF

cpu) display cpu information

mem)display mem information

disk)display disk information

*) quit

EOF


read -p "enter your choice:" choice


while [ "$choice" != "cpu" -a "$choice" != "mem" -a "$choice" != "disk" -a "$choice" != "*" ];do

echo "please make sure your choice"

read -p "enter your choice again:" choice

done


case $choice in

cpu)

lscpu;;

mem)

free

;;

disk)

fdisk -l /dev/[hs]d[a-z]

;;

*)

echo "quit"

exit 4

esac

[root@localhost sh]#


4、示例:写一个服务脚本:$lockfile 值:/var/lock/subsys/SCRIPT_NAME

要求:此脚本可接受start、stop、restart、status四个参数之一

如果参数非此四者,则提示使用帮助后退出

start,则创建lockfile,并显示启动

stop,则删除lockfile,并显示停止

restart,则先删除此文件,再创建此文件,而后显示重启完成

status,如果lockfile存在,则显示running,否则,则显示为stopped

[root@localhost init.d]# cat testservice

#!/bin/bash

#chkconfig: - 50 50

#description: test service script

prog=$(basename $0)

lockfile=/var/lock/subsys/$prog

case $1 in

start)

if [ -f $lockfile ];then

echo "$prog is running yet"

else

touch $lcokfile

[ $? -eq 0 ] && echo "start $rpog finished"

fi

;;

stop)

if [ -f $lockfile ];then

rm -rf $lockfile

[ $? -eq 0 ] && echo "stop $prog finished"

else

echo "prog is not runing"

fi;;

restart)

if [ -f $lockfile ];then

rm -rf $lockfile

touch $lockfile

echo "restart $prog finished"

else

touch -f $lockfile

echo "start $prog finished"

fi;;

status)

if [ -f $lockfile ];then

echo "$prog is running"

else

echo "$prog is stopped"

fi;;

*)

echo "usage:$prog {start | stop | restart | status}"

exit 5;;

esac

[root@localhost init.d]#


测试:

[root@localhost init.d]# cp testservice.sh /etc/init.d/

[root@localhost init.d]# chkconfig --add testservice.sh

[root@localhost init.d]# chkconfig --list testservice.sh

[root@localhost init.d]# chmod +x /etc/init.d/testservice.sh

[root@localhost init.d]# service testservice.sh start

[root@localhost init.d]# ls /var/lock/subsys/ //每个启动的服务在此目录下都有一个锁文件。





5、函数:function;对于过程式编程来讲,函数是实现代码重用的主要组件之一。


5.1、函数的定义:把一段独立功能的代码当做一个整体,并为它命名一个名字,即命名的代码段。注意:函数的代码段不会自己执行,它只能在被调用时才执行。


5.2、函数的调用:在代码中给定函数名即可;函数名出现的问题,在代码执行时都会被自动的替换为函数代码。


5.3、函数的功能:

①实现模块化编程

②实现结构化编程


5.4、函数的语法:

语法一:


function f_name{

函数体

}


注意:function是关键字,f_name是函数名,函数体在bash中编写的各类代码,无论是顺序的、选择的、循环的,都可以放在函数体中。

语法二:


f_name( ) {

函数体

}


注意:函数都有自己的生命周期:每次被调用时创建,返回时终止。

函数也有返回值:其状态返回结果为函数体中运行的最后一条命令的状态结果


5.5、自定义函数状态返回值:return

return用法:

return [0-255]

0:表示成功

1-255:表示失败

注意:函数中遇到return命令时,函数就不再往下运行了。


脚本的状态返回值:exit

exit用法:

exit [0-255]

0:表示成功

1-255:表示失败


5.6、函数示例:

①、给定一个用户名,通过脚本取得用户ID,和默认shell

未用函数实现:

[root@localhost sh]# cat fun_user.sh

#!/bin/bash

if id "$1" &> /dev/null;then

grep "^$1&;" /etc/passwd | cut -d: -f3,7

else

echo "no such user"

fi

[root@localhost sh]#


[root@localhost sh]# bash fun_user.sh root

0:/bin/bash

[root@localhost sh]#


用函数实现:

[root@localhost sh]# cat fun_user2.sh

#!/bin/bash

username=$1


get-userinfo() {

if id "${username}" &> /dev/null;then

grep "^${username}&;" /etc/passwd | cut -d: -f3,7

else

echo "no such user"

fi

}

get-userinfo //调用函数,只写函数名即可

[root@localhost sh]#


[root@localhost sh]# bash fun_user2.sh root

0:/bin/bash


注意:$1在函数中有特殊的用法,因此,此处用其他定义的变量代替
用函数实现,多次调用函数

[root@localhost sh]# cat fun_user3.sh

#!/bin/bash

get-userinfo() {

if id "${username}" &> /dev/null;then

grep "^${username}&;" /etc/passwd | cut -d: -f3,7

else

echo "no such user"

fi

}


username=$1

get-userinfo

username=$2

get-userinfo

[root@localhost sh]#


注意:由于没有设置return状态返回值,因此函数的状态返回值是函数体执行的最后一条语句的状态返回值。


②、用函数实现服务脚本框架

[root@localhost sh]# cat fun_testservice.sh

#!/bin/bash

#chkconfig: - 50 50

#decription: function testservice


prog=`basename $0`

lockfile=/var/lock/subsys/$prog

start() {

if [ -f $lockfile ];then

echo "$prog is running"

else

touch $lockfile && echo "start $prog finished"

fi

}


stop() {

if [ -f $lockfile ];then

rm -f $lockfile

[ $? -eq 0 ] && echo "stop $lockfile finished"

else

echo "$prog is not running"

fi

}


status() {

if [ -f $lockfile ];then

echo "$prog is running"

else

echo "$prog is stopped"

fi

}

usage() {

echo "usage $prog {start | stop | status | restart}"

}


case $1 in

start)

start;;

stop)

stop;;

restart)

start

stop

;;

status)

status;;

*)

usage

exit 1

;;

esac

[root@localhost sh]#



检查运行结果:

[root@localhost sh]# bash fun_testservice.sh status

[root@localhost sh]# bash fun_testservice.sh start

[root@localhost sh]# bash fun_testservice.sh stop

[root@localhost sh]# bash fun_testservice.sh restart

[root@localhost sh]# bash fun_testservice.sh s



注意:$0:脚本文件的名称



5.7、函数返回值:(有两种)

函数的执行结果返回值:

①、使用echo或printf命令进行输出,需要注意的是,printf不会换行,但可以格式化

②、函数体中调用的命令执行结果

函数的退出状态码:

①、默认取决于函数体中执行最后一条命令的退出状态码

②、自定义退出状态码:return #


5.8、函数可以接受参数:

传递参数给函数:

在函数体当中,可以使用$1,$2,$3,.....$n引用传递给函数的参数,还可以使用$*,$@应用所有参数,$#引用传递给函数参数的个数


怎么传递参数给函数?

在调用函数时,在函数名后面以空白字符分割,给定参数列表即可,如:funcation arg1 arg2 ...


5.9、给函数传递参数示例:

添加10个用户,添加用户的功能使用函数实现,用户名作为参数传递给函数。

[root@localhost sh]# cat fun_add_user.sh

#!/bin/bash

#description: user function to add user,username is argument

#date: 20180106


toadduser() {

if id $1 &>/dev/null;then

return 5//判断如果用户存在,则返回函数退出状态码5

else

useradd $1

retval=$?//将useradd $1的执行结果状态码赋值给变量retval

return $retval

fi

}


for ((i=1;i<=10;i++));do

toadduser ${1}${i}

retval1=$?//此处将函数的执行状态结果传递给变量retval1,为了在elif判断中 不去引用if的执行状态结果,

if [ $retval1 -eq 5 ];then

echo "user ${1}${i} is exists"

elif [ $retval1 -eq 0 ];then

echo "user ${1}${i} add sucessfull"

else

echo "unkown error"

fi

done

[root@localhost sh]#


注意:如果在循环语句中要引用函数的执行状态结果,最好将函数的执行状态结果$?赋值给变量。


5.10、练习:

5.10.1、写一个脚本,实现如下功能:

①、使用函数实现ping一个主机来测试主机的在线状态,并统计在线和不在线主机数;主机地址通过参数传递给函数

②、主程序:测试172.16.1.1 - 172.16.67.1范围内各主机的在线状态。

[root@localhost sh]# cat fun_userping.sh

#!/bin/bash

declare -i m=0

declare -i n=0

userping(){

ping -W 1 -c 1 $1 &> /dev/null

retval=$?

if [ $retval -eq 0 ];then

echo "$1 is online"

let m++

else

echo "$1 is offline"

let n++

fi

}

for ((i=1;i<=67;i++));do

userping 172.16.${i}.1

done

echo "online $m,offline $n"

[root@localhost sh]#


5.10.2、写一个脚本,实现打印NN乘法表,打印乘法表用函数实现

[root@localhost sh]# cat fun_NN_chengfabiao.sh

#!/bin/bash

nn() {

for ((i=1;i<=$1;i++));do

for((j=1;j<=i;j++));do

echo -n -e "${i}*${j}=$[${i}*${j}]t"

done

echo

done

}

nn $1

[root@localhost sh]#


5.11、变量作用域:

局部变量:作用域是函数的生命周期,在函数结束时,被自动销毁。

定义局部变量的方法:

在函数内部:local VARIABLE=VALUE //VARIABLE是变量名,value是变量值。


本地变量:作用域是运行脚本的shell的生命周期,因此,其作用范围为当前shell脚本程序文件。


示例说明:

[root@localhost sh]# cat var.sh

#!/bin/bash

name=tom

setname() {

name=jerry

echo "function:$name"

}

setname

echo "shell $name"

[root@localhost sh]#


[root@localhost sh]# bash var.sh

function:jerry

shell jerry

[root@localhost sh]#


[root@localhost sh]# cat var.sh

#!/bin/bash

name=tom

setname() {

local name=jerry

echo "function:$name"

}

setname

echo "shell $name"

[root@localhost sh]#


[root@localhost sh]# bash var.sh

function:jerry

shell tom

[root@localhost sh]#


输出结果都为jerry,原因是setname函数中定义的name可以调用脚本中定义的变量name

注意:建议在写函数中的变量定义时,全部定义为局部变量,除非打算和主程序进行交互传递值。


5.12、函数递归:常用在阶乘、和数列中。

阶乘示例:

[root@localhost sh]# cat fun_jc.sh

#!/bin/bash

fact() {

if [ $1 -eq 0 -o $1 -eq 1 ];then

echo 1

else

echo $[$1*$(fact $[$1-1])]

fi

}

fact $1

[root@localhost sh]#


[root@localhost sh]# bash fun_jc.sh 4

24

[root@localhost sh]#


数列示例:

[root@localhost sh]# cat fun_sl.sh

#!/bin/bash

fab() {

if [ $1 -eq 1 ];then

echo -n "1 "

elif [ $1 -eq 2 ];then

echo -n "1 "

else

echo -n "$[$(fab $[$1-1])+$(fab $[$1-2])] "

fi

}

for i in $(seq 1 $1);do

fab $i

done

echo

[root@localhost sh]#



[root@localhost sh]# bash fun_sl.sh 10

1 1 2 3 5 8 13 21 34 55

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读