设为首页 收藏本站
查看: 730|回复: 0

shell 脚本 -select总结

[复制链接]
发表于 2018-8-24 07:41:27 | 显示全部楼层 |阅读模式
  描述:
  select控制语句基于Korn Shell中的控制结构
  select语句首先显示一个菜单,然后根据用户的选择给变量赋予相应的值,最后执行一系列命令。
  语法:
  select varname [ in arg...]
  do
  commands
  done
  说明:
  select结构显示arg项的菜单。加入忽略关键字in和参数列表,select控制语句就用位置参数来取代arg项。select的菜单格式化为在每一项前加一个数字。
  select循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准输出上,并显示PS3提示符,等待用户输入
  用户输入菜单列表中的某个数字,执行相应的命令。
  用户输入被保存在内置变量REPLY中。
  select是个无限循环,使用break命令退出循环,或用exit命令终止脚本,也可以按ctrl+c推出循环
  select经常和case联合使用
  与for循环类似,可以省略in list,此时使用位置参数
  示例:
#!/bin/bash  
PS3="Please guss which fruit I like:"
  
select var in "apple" "pear" "orange" "peach";do
  
  if [ "$var" == "apple" ];then
  
    echo "You are right"
  
    break
  
  else
  
    echo "try again"
  
  fi
  
done
  
[root@localhost ~]# bash a.sh
  
1) apple
  
2) pear
  
3) orange
  
4) peach
  
Please guss which fruit I like:2
  
try again
  
Please guss which fruit I like:3
  
try again
  
Please guss which fruit I like:4
  
try again
  
Please guss which fruit I like:1
  
You are right
  函数:
  函数(function)是由若干条shell命令组成的语句块,实现代码重用和模块化编程,
  它与shell程序形式上是相似的,不同的是它不是一个单独的进程,不能独立运行,而是shell程序的一部分
  函数和shell程序的区别在于:
  shell程序在子shell中运行,而shell函数在当前shell中运行。因此在当前shell中,函数可以对shell中的变量进行修改
  函数由两部分组成:函数名和函数体
  语法一:
  function NAME {
  函数体
  }
  语法二:
  NAME() {
  函数体
  }
  函数的使用:
  可以在交互式环境下定义函数
  可将函数放在脚本文件中作为它的一部分
  可放在只包含函数的单独文件中
  调用:函数只有被调用才会执行
  调用:给定函数名
  函数名出现的地方,会被自动替换为函数代码
  函数的生命周期:被调用时创建,返回时终止
  函数的执行结果返回值:
  1,使用echo或printf命令进行输出
  2,函数体调用命令的输出结果
  函数的退出状态码:
  1,默认取决于函数最后一条命令的退出状态码
  2,自定义退出状态码,其格式为:
  return 从函数中返回,用最后状态命令决定返回值
  return 0 正确返回
  return 1-255 有错误返回
  交互式环境下定义和使用函数
  示例:
[root@localhost ~]# dir(){  
> ls -l            定义该函数后,在命令行直接键入dir,其显示结果同ls -l的作用相同
  
> }
  
[root@localhost ~]# dir
  
-rw-r--r--. 1 root root  205 Aug 19 17:55 a.sh
  
-rwxr-xr-x. 1 root root  106 Aug 12 05:42 backup.sh
  
drwxr-xr-x. 2 root root 4096 Aug 15 06:28 bin
  
[root@localhost ~]# unset dir    从当前系统中退出该dir函数
  在脚本中定义及使用函数
  函数在使用前必须定义,因此应该将函数定义放在脚本开始部分,直到shell首次发现它后才能使用
  调用函数仅使用其函数名即可
  示例:
[root@localhost ~]# cat func1  
#!/bin/bash
  
#func1
  
hello(){
  
echo "Hello there today's date is `date +%F`"
  
}
  
echo "now going to the function hello"
  
hello
  
echo "back from the function"
  
[root@localhost ~]# chmod +x func1
  
[root@localhost ~]# ./func1
  
now going to the function hello
  
Hello there today's date is 2016-08-21
  
back from the function
  使用函数文件
  可以将经常使用的函数存入函数文件,然后将函数文件载入shell
  文件名可任意取,但最后与相关任务有某种联系。例如:functions.main
  一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用set命令查看所有定义的函数,其输出列表包括已经载入shell的所有函数
  若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载入此文件
  创建函数文件:
  示例:
[root@localhost ~]# cat function.main       函数文件  
#!/bin/bash
  
#functions.main
  
findit() {
  
  if [ $# -lt 1 ];then
  
    echo "Usage:findit file"
  
    return 1
  
  fi
  
  find / -name $1 -print
  
}
  函数文件已创建好后,要将它载入shell
  定位函数文件并载入shell格式:
  . filename 或 source filename   (即  )   (这里的文件名要带正确路径)
  使用set命令检查函数是否已载入。set命令将在shell中显示所有已载入的函数
[root@localhost ~]# . function.main  
[root@localhost ~]# set
  
findit ()
  
{
  
    if [ $# -lt 1 ]; then
  
        echo "Usage:findit file";
  
        return 1;
  
    fi;
  
    find / -name $1 -print
  
}
  
[root@localhost ~]# findit groups   执行shell函数,键入函数名即可
  
/usr/bin/groups
[root@localhost ~]# unset findit     删除shell函数(命令格式为:unset function_name)  
[root@localhost ~]# set     函数findit无显示
  函数参数:
  传递参数给函数:调用函数时,在函数名后面以空白分隔给定参数列表即可;例如:"findit a b ..."
  在函数体中当中,可使用$1,$2,...调用参数,还可以使用$@,$*,$#等特殊变量
  函数变量:
  环境变量:当前shell和子shell有效
  本地变量:只在当前shell进程有效,为执行脚本会启动专用子shell进程;因此,本地变量的作用范围是当前shell脚本程序文件,包括脚本中的函数
  局部变量:函数的生命周期;函数结束时变量被自动销毁
  注意:如果函数中有局部变量,如果其名称同本地变量,使用局部变量
  在函数中定义局部变量的方法: local NAME=VALUE
  函数递归示例:
[root@localhost ~]# cat fact.sh  
#!/bin/bash
  
fact() {
  
  if [ $1 -eq 0 -o $1 -eq 1 ];then
  
echo 1
  
  else
  
echo $[$1*$(fact $[$1-1])]
  
  fi
  
}
  
fact 4
  
[root@localhost ~]# bash -x fact.sh
  
+ fact 4
  
+ '[' 4 -eq 0 -o 4 -eq 1 ']'
  
++ fact 3
  
++ '[' 3 -eq 0 -o 3 -eq 1 ']'
  
+++ fact 2
  
+++ '[' 2 -eq 0 -o 2 -eq 1 ']'
  
++++ fact 1
  
++++ '[' 1 -eq 0 -o 1 -eq 1 ']'
  
++++ echo 1
  
+++ echo 2
  
++ echo 6
  
+ echo 24
  
24
  作业:
  1、写一个服务脚本/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为当前脚本名
[root@localhost function]# cat testsrv.sh  
#!/bin/bash
  
fstart () {
  
  if [ -e "$1" ];then
  
     echo "Already Start"
  
  else
  
     touch $File
  
     echo "Start Successfully!"
  
  fi
  
}
  
fstop() {
  
  if [ -e "$1" ];then
  
     rm -f $File
  
     echo "Stop Successfully!"
  
  else
  
     echo "Already stop"
  
  fi
  
}
  
frestart() {
  
  if [ -e "$1" ];then
  
     fstop &> /dev/null
  
     fstart &> /dev/null
  
     echo "Restart Successfully!"
  
  else
  
     fstart &> /dev/null
  
     echo "Start Successfully!"
  
  fi
  
}
  
fstatus() {
  
  if [ -e "$1" ];then
  
     echo "testsrv is running"
  
  else
  
     echo "testsrv has been stop"
  
  fi
  
}
  
select choice in start stop restart status quit;do
  
  File=/var/lock/subsys/testsrv.sh
  
    case $choice in
  
    start)
  
       fstart $File
  
       ;;
  
    stop)
  
       fstop $File
  
       ;;
  
    restart)
  
       frestart $File
  
       ;;
  
    status)
  
       fstatus $File
  
       ;;
  
    quit)
  
       break
  
       ;;
  
     *)
  
       echo "error,please choose again"
  
       exit 2
  
     esac
  
done
  
[root@localhost function]# bash testsrv.sh
  
1) start
  
2) stop
  
3) restart
  
4) status
  
5) quit
  
#? 4
  
testsrv is running
  
#? 3
  
Restart Successfully!
  
#? 1
  
Already Start
  
#? 2
  
Stop Successfully!
  
#? 5
  2、编写一个脚本/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/ldlinux-x86-64.so.2
  (5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命
  令,并重复完成上述功能;直到用户输入quit退出
[root@localhost ~]# cat copycmd.sh  
#!/bin/bash
  
ch_root="/mnt/sysroot/"
  
[ ! -d $ch_root ] && mkdir $ch_root
  
bincopy() {
  
   if which $1 &>/dev/null;then
  
      local cmd_path=`which --skip-alias $1`
  
      local bin_dir=`dirname $cmd_path`
  
      [ -d ${ch_root}${bin_dir} ] || mkdir -p ${ch_root}${bin_dir}
  
      [ -f ${ch_root}${cmd_path} ] || cp $cmd_path ${ch_root}${bin_dir}
  
      return 0
  
   else
  
      echo "Command not found"
  
      return
  
   fi
  
}
  
libcopy() {
  
   local lib_list=$(ldd `which --skip-alias $1` | grep -Eo '/[^[:space:]]+')
  
   for loop in $lib_list;do
  
       local lib_dir=`dirname $loop`
  
       [ -d ${ch_root}${lib_dir} ] || mkdir -p ${ch_root}${lib_dir}
  
       [ -f ${ch_root}${loop} ] || cp $loop ${ch_root}${lib_dir}
  
   done
  
}
  
read -p "Please input a command:" command
  
while [ "$command" != "quit" ];do
  
    if bincopy $command;then
  
         libcopy $command
  
    fi
  
    read -p "Please input a command or quit:" command
  
done
  
[root@localhost ~]# ll /mnt/sysroot/lib64
  
-rwxr-xr-x. 1 root root  164432 Aug 23 15:28 ld-linux-x86-64.so.2
  
-rwxr-xr-x. 1 root root   37056 Aug 23 15:28 libacl.so.1
  
-rwxr-xr-x. 1 root root   19888 Aug 23 15:28 libattr.so.1
  
-rwxr-xr-x. 1 root root   20024 Aug 23 15:28 libcap.so.2
  
-rwxr-xr-x. 1 root root 2107816 Aug 23 15:28 libc.so.6
  
-rwxr-xr-x. 1 root root   19512 Aug 23 15:28 libdl.so.2
  
-rwxr-xr-x. 1 root root  153192 Aug 23 15:28 liblzma.so.5
  
-rwxr-xr-x. 1 root root  398272 Aug 23 15:28 libpcre.so.1
  
-rwxr-xr-x. 1 root root  142296 Aug 23 15:28 libpthread.so.0
  
-rwxr-xr-x. 1 root root  147120 Aug 23 15:28 libselinux.so.1
  
[root@localhost ~]# ll /mnt/sysroot/usr/bin
  
-rwxr-xr-x. 1 root root  54048 Aug 23 15:41 cat
  
-rwxr-xr-x. 1 root root 117616 Aug 23 15:35 ls
  3、写一个函数实现两个数字做为参数,返回最大值
#!/bin/bash  
function NUMBER {
  
if [ $1 -lt $2 ];then
  
    echo "The max number is $2"
  
elif [ $1 -eq $2 ];then
  
    echo "The two number is equal"
  
else
  
    echo "The max number is $1"
  
fi
  
}
  
NUMBER $1 $2
[root@localhost function]# bash test3.sh 3 5  
The max number is 5
  
[root@localhost function]# bash test3.sh 6 4
  
The max number is 6
  
[root@localhost function]# bash test3.sh 8 8
  
The two number is equal
  4、写一个函数实现数字的加减乘除运算,例如输入 1 + 2,将得出正确结果
[root@localhost function]# cat test4-1.sh  
#!/bin/bash
  
fjia() {
  
   sum=$[$1+$2]
  
   echo "$sum"
  
}
  
fjian() {
  
   sum=$[$1-$2]
  
   echo "$sum"
  
}
  
fcheng() {
  
   sum=$[$1*$2]
  
   echo "$sum"
  
}
  
fchu() {
  
   sum=$[$1/$2]
  
   echo "$sum"
  
}
  
read -p "please input: " a b c
  
   case $b in
  
   +)
  
      fjia $a $c
  
      ;;
  
   -)
  
      fjian $a $c
  
      ;;
  
   \*)
  
      fcheng $a $c
  
      ;;
  
   /)
  
      fchu $a $c
  
      ;;
  
   *)
  
      echo "please input correct form"
  
      exit 3
  
   esac
  
[root@localhost function]# bash test4-1.sh
  
please input: 6+7
  
please input correct form
  
please input: 6 + 7
  
13
  
please input: 6 - 8
  
-2
  
please input: 2 * 3
  
6
  
please input: 4 / 2
  
2
  5、斐波那契数列又称黄金分割数列,因数学家列昂纳多·斐波那契以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列: 0、 1、 1、 2、 3、 5、 8、 13、 21、 34、 ……,斐波纳契数列以如下被以递归的方法定义: F( 0) =0, F( 1) =1, F( n) =F(n-1)+F(n-2)(n≥2)
  写一个函数,求n阶斐波那契数列
[root@localhost function]# cat test5-1.sh  
#!/bin/bash
  
ftzsl() {
  
   if [ $1 -eq 0 ];then
  
      echo "0"
  
   elif [ $1 -eq 1 ];then
  
      echo "1"
  
   else
  
      echo "$[$(ftzsl $[$1-1])+$(ftzsl $[$1-2])]"
  
   fi
  
}
  
read -p "please input a number: " n
  
   ftzsl $n
  
[root@localhost function]# bash test5-1.sh
  
please input a number: 5
  
5
  
please input a number: 6
  
8
  6、汉诺塔(又称河内塔)问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间
  一次只能移动一个圆盘。利用函数,实现N片盘的汉诺塔的移动步骤
[root@localhost function]# cat test6.sh  
#!/bin/bash
  
fpan() {
  
  if [ $1 -eq 1 ];then
  
     echo "$2 ==> $4"
  
  else
  
     fpan $[$1-1] $2 $4 $3
  
          echo "$2 ==> $4"
  
     fpan $[$1-1] $3 $2 $4
  
  fi
  
}
  
fpan $1 a b c
  
[root@localhost function]# bash test6.sh 2
  
a ==> b
  
a ==> c
  
b ==> c



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-555710-1-1.html 上篇帖子: shell 脚本 -select总结 下篇帖子: SHELL中的引用之引用变量
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表