shell编程之循环及函数

for 循环

for 变量名 in 列表;do

   循环体

done  

执行机制: 依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中

的元素耗尽,循环结束

 

列表生成方式:

(1)直接给出列表

(2)整数列表:

(a) {start..end}

(b) $(seq [start [step]] end)  : `seq 1 2 100`

(3)返回列表的命令 $(COMMAND)

(4)使用glob,如:*.sh

(5)变量引用;$@, $*

 

while 循环

while CONDITION;do

循环体

  done

   CONDITION :循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判  断;条件为“true”则执行一次循环;直到条件测试状态为“false”终止循环

 因此:CONDTION 一般应该有循环控制变量;而此变量的值会在循环体不断地被修正

 进入条件:CONDITION true 退出条件:CONDITION false

 

until 循环

until CONDITION;do

循环体

   done

 进入条件:CONDITION true 退出条件:CONDITION false

 

循环控制语句continue

用于循环体中

continue [N] :提前结束第N 层的本轮循环,而直接进入下一轮判断;最内层为第1

while CONDTIITON1; do

CMD1

if CONDITION2; then

continue

fi

CMDn

done

 

循环控制语句break

用于循环体中

break [N] :提前结束第N 层循环,最内层为第1

while CONDTIITON1; do

CMD1

if CONDITION2; then

break

fi

CMDn

done

 

创建无线循环

while true;do

   循环体

done

until falsedo

    循环体

done

 

while 循环的特殊用法(遍历文件的每一行)

while read line; do

循环体

done < /PATH/FROM/SOMEFILE

依次读取/PATH/FROM/SOMEFILE 文件中的每一行,且将行赋值给变量line

 

for 循环的特殊格式:

for (( 控制变量初始化; 条件判断表达式; 控制变量的修正表达式))

do

循环体

done

控制变量初始化:仅在运行到循环代码段时执行一次

控制变量的修正表达式: 每轮循环结束会先进行控制变量修正运算,而后再做条件判断

双小括号方法,即(()) 格式,如((i=1,i++,i<=10))

 

例:

 blob.png

打印310~20(排除15

continue改为continue 2 break  跳出里面的for循环,则打印310~14

若改为break 2,则跳出整个循环,只打印10~14

 

select循环与菜单

select variable in list

do

循环体命令

done

select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示PS3提示

示符,等待用户输入

用户输入菜单列表中的某个数字,执行相应的命令

用户输入被保存在内置变量 REPLY

select是个无限循环,因此要记住用break命令退出循环,或用 exit命令终止脚本,

也可以按 ctrl+c退出循环。select 经常和case联合使用

1: select cmd in ls pwd  hostname exit;do $cmd;done

blob.png

注意:输入4,执行exit就登出shell 

2

blob.png

blob.png

 

 

函数

function f_name {

    函数体

}

f_name() {

    函数体

}

函数的定义和使用:

    可在交互式环境下定义函数

    可将函数放在脚本文件中作为它的一部分

    可放在只包含函数的单独文件中

调用:函数只有被调用才会执行;

    调用:给定函数名

    函数名出现的地方,会被自动替换为函数代码

函数的生命周期:被调用时创建,返回时终止

 

函数的执行结果返回值:

    (1) 使用echo printf 命令进行输出

    (2) 函数体中调用命令的输出结果

函数的退出状态码:

    (1) 默认取决于函数中执行的最后一条命令的退出状态码

    (2) 自定义退出状态码,其格式为:

    return 从函数中返回,用最后状态命令决定返回值

return 0 无错误返回

return 1-255 有错误返回

 

使用函数文件

可以将经常使用的函数存入函数文件,然后将函数文件载入shell

一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用set命令查看所有定义的函数,其输出列表包括已经载入shell 的所有函数;若要改动函数,首先用unset命令从shell中删除函数,改动完毕后,再重新载入此文件

function fun1 (){ echo "this is a fun1";}

# fun1  输出this is a fun1

set命令看到存在内存中的变量fun1

unset fun1 set查看就没有这个变量了,# fun1 输出command not found

 

function fun3 () { echo "this is a func3";return;echo "xxxx"; }

#fun3 只输出this is a func3  return后面的不执行

echo $? 返回0

return后面自定义级别,如return 100

执行fun3 echo $? 返回100


载入函数

filename source filename


函数变量

变量作用域:

环境变量:当前shell和子shell有效

本地变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程;因此本地变量的作用范围是当前shell 脚本程序文件,包括脚本中的函数。

局部变量:函数的生命周期;函数结束时变量被自动销毁

注意:如果函数中有局部变量,如果其名称同本地变量,使用局部变量

  在函数中定义局部变量的方法 local NAME=VALUE


1.判断/var/ 目录下所有文件的类型

 blob.png

  for i in /var/*;do echo $i|filetype.sh;done |sed -n '2~2p'    (用到函数调用)

2.添加10个用户user1-user10,密码同用户名

 #!/bin/bash

for i in {1..10}

do

useradd user$i

echo "user$i"|passwd –stdin user$i

done

3./etc/rc.d/rc3.d 目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,以K 开头的文件输出为文件加stop,以S开头的文件输出为文件名加start;

  “K34filename stop” “S66filename start”

  #!/bin/bash

cd /etc/rc.d/rc3.d

for i in /etc/rc.d/rc3.d/*;do

b=`basename /etc/rc.d/rc3.d/$i`

j=`echo $b|cut -c1`

     if [ $j == 'K' ];then

     cp $b "$b"_stop

     elif [ $j == 'S' ];then

     cp $b "$b"_start

     fi

done

blob.png

4.写一个脚本,提示输入正整数n 的值,计算1+2+3+…n的总和

  #!/bin/bash

read -p "Input a positive number: " n

if [ $[$n/1] -gt 0 ];then

    echo sum=`seq -s+ 1 $n|bc`

elif [ $[$n/1] -lt 0 ];then

    echo negative number is not allowed

elif [ $n == 0 ];then

    echo Zero!

else

    echo other input is illegal

fi

blob.png

5.写一个脚本,提示请输入网络地址,如172.18.18.0 ,判断输入的网段中主机在线状态

#!/bin/bash

    for ip in `seq 1 255`

    do

    {

    ping -c 1 172.18.18.$ip > /dev/null 2>&1

    if [ $? -eq 0 ]; then

    echo 172.18.18.$ip UP

    else

    echo 172.18.18.$ip DOWN

    fi

    }&

    done

6.打印乘法表(if / while

#!/bin/sh

  for i in {1..9};do

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

      echo -n "$j*$i=$(($j*$i)) "

      if [ $j -ge $i ];then

       echo

       break

      fi

    done

done

#!/bin/sh

i=1

j=1

while [ "$i" -ne 10 ];do

    while [ "$j" -le $i ];do

        echo -ne "$i*$j=$(($i*$i)) \t"

        let j++

    done

    j=1

    let i++

    echo

done

blob.png

7.100以内所有正整数之和(while)

#!/bin/bash

read -p "Input a positive number: " n

a=0

while [ $a -le $n ];do

sum=`seq -s+ 1 $a`

let a++

done

echo $sum|bc

blob.png

8.通过ping 命令探测192.168.1.1-254范围内的所有主机的在线状态,统计在线主机和离线主机各多少

#!/bin/bash

read -p "Input the ip: " ip

i=`echo $ip | cut -d. -f1-3`.

j=0

if echo $ip | egrep "^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]).(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5]).){2}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$" ;then

  while [ $j -le 255 ] ;do

    ping -c1 -W1 $i$j &> /dev/null  && echo "$i$j is online" ||echo "$i$j is offline"

    let j++

  done

else

  echo "Illegal input"

fi

blob.png

9.利用变量RANDOM生成10个随机数字,输出这个10数字,并显示其中的最大者和最小者(while)

#!/bin/bash

echo > rnu

frequency=1

while [ $frequency -le 10 ];do

    echo $[$RANDOM] >> rnu

let frequency++

done

ten_random=`cat rnu|sed -e 1d`

echo  "Ten random number are"

echo $ten_random

echo -e "\033[31mmax=`cat rnu|tr " " "\n"|sort -n|tail -1`\033[0m"

echo -e "\033[32mmin=`cat rnu|tr " " "\n"|sort -n|sed -n 2p`\033[0m"

blob.png

10.打印国际象棋棋盘

 #!/bin/bash

for i in {1..8}; do

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

       if [ $[($i+$j)%2] -eq 0 ]; then

         echo -ne "\033[47m  \033[0m"

       else

         echo -ne "\033[40m  \033[0m"

       fi

     if [ $j -eq 8 ]; then

       echo -ne "\n"

     fi

     done

done

blob.png

11.每隔3秒钟到系统上获取已经登录的用户的信息;如果发现用户hacker 登录,则将登录时   间和主机记录于日志/var/log/login.log , 并提示该用户退出系统

#!/bin/bash

until who |grep -q "^hacker\b" ;do

    sleep 3

done

who | grep "^hacker"|tr -s ' '|cut -d' ' -f3,5 >> /var/log/login.log

echo "you should logout system" | mail hacker

echo "reminded and login record in /var/log/login.log"

blob.png

12. 随机生成10以内的数字,实现猜字游戏,提示比较大或小,相等则退出。

  #!/bin/bash

  read -p "Input a number: " m

  n=$[$RANDOM%10+1]

  until [[ $m -eq $n ]];do

    [ $m -lt $n ] && echo "It's small,guess bigger"

    [ $m -gt $n ] && echo "It's big,guess smaller"

    read -p "Input a number: " m

  done

  echo Right!

  blob.png 

13.打印松塔

 #!/bin/bash

 #i是当前行数,j是空格数量,h是星号数量

read -p "Please Enter a number:" Row

for ((i=1; i<=Row; i++))

do

        for ((j=$Row-$i; j>0; j–));

        do

              echo -n ' '

        done

        for ((h=1; h<=$((2*$i-1)); h++))

        do

              echo -ne '\033[32m*\033[0m'

        done

        echo

done

blob.png

14.until循环实现国际象棋棋盘

 #!/bin/bash

i=1

j=1

until [ $i -gt 8 ]

do

      until [ $j -gt 8 ]

      do

          if [ $[(($i+$j))%2] -eq 1 ];then

                echo -ne "\033[47m  \033[0m"

          else

                echo -ne "\033[40m  \033[0m"

          fi

       let j++

      done

      echo

let i++

j=1

done

 blob.png

15.编写服务脚本/root/bin/testsrv.sh,完成如下要求

(1) 脚本可接受参数:start, stop, restart, status

(2) 如果参数非此四者之一,提示使用格式后报错退出

(3) 如是start:则创建/var/lock/subsys/SCRIPT_NAME, 并显示“启动成功”

考虑:如果事先已经启动过一次,该如何处理?

(4) 如是stop:则删除/var/lock/subsys/SCRIPT_NAME, 并显示“停止完成”

考虑:如果事先已然停止过了,该如何处理?

(5) 如是restart,则先stop, 再start

考虑:如果本来没有start,如何处理?

(6) 如是status, 则如果/var/lock/subsys/SCRIPT_NAME文件存在,则显示“SCRIPT_NAME is   running…”

如果/var/lock/subsys/SCRIPT_NAME文件不存在,则显示“SCRIPT_NAME is stopped…”

其中:SCRIPT_NAME为当前脚本名

#!/bin/bash

fstart () {

    if [ -e "$1"  ]; then

        echo "Already start"

    else

        touch $ff

        echo "Start Successfully!"

    fi

} 

fstop () {

    if [ -e "$1" ] ; then

        rm -f $1

        echo "Stop Successfully!"

    else

        echo "Already stop"

    fi

} 

frestart() {

    if [ -e "$1" ] ; then

        fstop &> /dev/null

        fstart &> /dev/null

        echo "Restart successful"

    else

        fstart &> /dev/null

        echo "start successful "

    fi

} 

fstatus () {

    if [ -e "$1" ] ;then

        echo "testsrv is runing…"

    else

        echo "testsrv is stopped…"

    fi

} 

select choice in start stop restart status quit

do

    ff=/var/lock/subsys/testsrv.sh

    case $choice in

    start)

        fstart $ff

        ;;

    stop)

        fstop $ff

        ;;

    restart)

        frestart $ff

        ;;

    status)

        fstatus $ff

        ;;

    quit)

        break

        ;;

    *)

        echo "error!"

        exit 2

    esac

done

 blob.png

16. 编写脚本/root/bin/copycmd.sh

(1)提示用户输入一个可执行命令名称;

(2)获取此命令所依赖到的所有库文件列表

(3)复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下;

  如:/bin/bash ==> /mnt/sysroot/bin/bash

   /usr/bin/passwd==> /mnt/sysroot/usr/bin/passwd

(4)复制此命令依赖到的所有库文件至目标目录下的对应路径下:

  如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2

(5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上  述功能;直到用户输入quit退出

#!/bin/bash

copycmd(){

for eachline in `ldd $fullname | sed -r -n 's@.*> (/.*) \(.*$@\1@p'`

do

   local path=`dirname $eachline`

   mkdir -p /mnt/sysroot/$path &>/dev/null

   cp -p $eachline  /mnt/sysroot/$path &>/dev/null

done

}

while true

do

read -p "请输入一个可执行的命令名称 " cmds

which $cmds

if [ $? -eq 0 ]

then

   fullname=`\which $cmds`

   path=`dirname $fullname`

   mkdir -p /mnt/sysroot/$path &>/dev/null

   cp -p $fullname  /mnt/sysroot/$path &>/dev/null

   copycmd

elif [[ $cmds == "quit" ]]

then

   break

else

   echo "输入的命令不对"

fi

done

blob.png

blob.png

17.写一个函数实现数字的加减乘除运算,例如输入1+2 ,将得出正确结果

 vim mathfun

#!/bin/bash

function multiplications () {

let multiplication=$1\*$2

echo "积为:$multiplication"

}

function divisions () {

let division=$1/$2

echo "商为:$division"

}

function pluss () {

let plus=$1+$2

echo "和为:$plus"

}

function subtractions {

let subtraction=$1-$2

echo "差为:$subtraction"

}

vim funset

#!/bin/bash

source mathfun

echo "1st arg is $1"

echo "2st arg is $2"

pluss $1 $2

divisions $1 $2

multiplications $1 $2

subtractions $1 $2

blob.png

18. 0,1,2,3,5,8,13,21,34…… ,斐波纳契数列以如下被以递归的方法定义:

   F(0)=0 ,F(1)=1 ,F(0)=F(n-1)+F(n-2) n2

写一个函数,求n阶斐波那契数列

#!/bin/bash

rabbit() {

    if [ $1 -eq 0 ];then

        echo 0

    elif [ $1 -eq 1 ];then

        echo 1

    else

        echo "$[$(rabbit $[$1-1])+$(rabbit $[$1-2])]"

    fi

}

rabbit $1

blob.png

19.利用函数,实现N片盘的汉诺塔的移动步骤

#!/bin/bash

hannuo() {

    if [ $1 -eq 1 ];then

        echo "from $2 to $4"

    else

        hannuo `expr $1 – 1` $2 $4 $3

        echo "from $2 to $4"

        hannuo `expr $1 – 1` $3 $2 $4

    fi

}

read -p "Input the number: " n

hannuo $n 'A' 'B' 'C'

blob.png

20.扫描/etc/passwd 文件每一行,如发现GECOS 字段为空,则填充用户名和单位电话为62985        6并提示该用户的GECOS信息修改成功

#!/bin/bash

    while read line ; do

        var=`echo $line | cut -d ":" -f 5`

        user=`echo $line | cut -d ":" -f 1`

        [[ -z "${var}" ]] && chfn -f ${user} -p 629856 ${user};echo "${user}'s information

    change successful"

    done < /etc/passwd

 blob.png



原创文章,作者:victorycommander,如若转载,请注明出处:http://www.178linux.com/39013

(0)
victorycommandervictorycommander
上一篇 2016-08-24
下一篇 2016-08-24

相关推荐

  • 计算机网络基础知识与Linux网络配置

    本文主要内容是: 1.讲述网桥、集线器、二层交换机、三层交换机、路由器的功能、使用场景与区别。 2、IP地址的分类有哪些?子网掩码的表示形式及其作用 3、计算机网络的分成模型有哪些(OSI模型和TCP/IP模型),每一层的功能及涉及到的物理设备有哪些。 4、如何给网络接口配置多个地址,有哪些方式? 5、常用的网络管理类工具有哪些,并用示例形式描述他们的使用方…

    Linux干货 2016-11-14
  • N26-第三周博客作业

    1、  列出当前系统上所有已经登录的用户的用户名,注意:同一个用户登录多次,则只显示一次即可。 命令:who | cut -d' ' -f1 | sort –u 涉及知识点: l  who命令 作用:查看当前所有的登录会话 l  cut命令 作用:将文本内容按照指定内容分割,然后取出指定字段。 常用选项: &…

    Linux干货 2017-02-10
  • Linux启动流程

    内核级别: 1、POST开机加电自检 BIOS加载CMOS信息并进行开机自检,检测硬件设备是否正常并进行硬件设备初始化 2、Boot Sequence(BIOS):定义设备启动顺序 BIOS定义设备启动顺序,并读取启动设备数据加载硬盘上的第一个扇区MBR。 3、Boot Loader(MBR):bootloader功能实现 Boot Loader提供一个菜单…

    Linux干货 2016-11-23
  • nginx+varnish+httpd小试牛刀

    简介: Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的 squid 相比,varnish 具有性能更高、速度更快、管理更加方便等诸多优点; 此次试验的目的是让Nginx做前端访问负载均衡,varnish代理后端的web服务器,并缓存结果 1.准备机器,做好时间同步,主机名解…

    Linux干货 2017-06-27
  • linux文件管理命令与命令行展开

    linux文件管理命令与命令行展开

    2017-12-11
  • YUM工具的工作原理、用法及源 码包的编译安装

    YUM工具的工作原理,用法及源码包的编译安装 _ueditor_page_break_tag_ 一、 CentOS: yum, dnf       1.YUM: (Yellow dogUpdate Modifier),rpm的前端程序,用来解决软件包相关依赖性,可以在多个库之间定位软件包,up2date的替代工具   …

    Linux干货 2016-09-01