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

Linux Shell——流程控制

[复制链接]

尚未签到

发表于 2018-8-24 13:26:16 | 显示全部楼层 |阅读模式
一. 创建交互式脚本
使用 echo命令的选项
  关于各种命令的使用,可以使用man 命令来查看命令的详细用法介绍。例如,我想看下 echo 的用法和各种选项。可以执行 man echo。执行结果如下:
  如果单独执行 echo 命令,就会打印出一个空白行。
  默认情况下,echo 都会换行,如果不想换行的话,可以使用下面两种方式的一种。
echo -n "Which directory do you want to use? "  
echo -e "Which directory do you want to use? \c"
使用 read 命令
  如果我们需要读入用户输入的参数时,可以使用 read 命令,当然还可以从文件系统等读入信息。
  我们建立一个新的脚本文件 hello3.sh。
#!/bin/bashecho -n "Hello I  $(basename $0) may I ask your name: "readecho "Hello $REPLY"exit 0  执行此脚本时,首先提示需要输入,然后输入的内容,REPLY当没有给read提供参数时设置,最后打印出来。
  执行结果为:
优化 read 提示的脚本
  在前面的例子中,我们使用了echo -n的方式来阻止信息换行,其实 read 命令也带了一个选项来实现相同的功能:
read -p "Enter your name: " name  上面的脚本中,我们定义了一个变量name用来保存输入的内容,如果不定义变量的话,输入的内容会保存在REPLY中。
  下面是具体使用的语法:
  hello3.sh的脚本可以改成如下:
#!/bin/bashread -p "May I ask your name: " nameecho "Hello $name"exit 0限制输入内容的个数
  我们还可以使用 read命令的-n 选项,此选项后面需要接一个数字,可以限制输入内容的个数。
#!/bin/bashread -p "May I ask your name: " nameecho "Hello $name"read -n1 -p "Press any key to exit"echoexit 0控制输入内容的可见性
  目前,我们输入的内容都是可见的,但有些敏感的数据,如密码,信用卡号等信息,输入时并不想可见。那么可以使用read -s。
  这时再输入时,就有一个钥匙的标识,而且输入时不可见。
实例演示
  现在有一个小程序,要求把指定后缀的文件备份到指定的目录下,代码如下:
#!/bin/bash# Script to prompt to back up files and location# The files will be search on from the user's home# directory and can only be backed up to a directory within $HOMEread -p "Which file types do you want to backup " file_suffixread -p "Which directory do you want to backup to " dir_name# The next lines creates the directory if it does not existtest -d $HOME/$dir_name || mkdir -m 700 $HOME/$dir_name# The find command will copy files the match the# search criteria ie .sh . The -path, -prune and -o# options are to exclude the back directory from the# backup.find $HOME -path $HOME/$dir_name -prune -o \  
-name "*$file_suffix" -exec cp {} $HOME/$dir_name/ \;exit 0
二. 条件判断语句
使用test 内建函数
  test命令是 shell 环境中用于测试条件表达式的工具。
  它的返回值可以是 true,false,0或1。基本语法为:
test EXPRESSION  如果我们需要多个表达式,可以使用AND,OR,对应的选项为-a,-o。
test EXPRESSION -a EXPRESSIONtest EXPRESSION -o EXPRESSION  其实,在实际应用中,test 有种非常简洁的方式,就是被中括号包含的条件表达式。这种方式更加常用。语法如下:
[ EXPRESION ]  test 的用法很多,例如,可以比较两个字符串是否相等:
[ $USER = root ]  我们还可以test 的选项来判断一个字符串的长度是否为0。
[ -z $1 ]  上面的代码的含义是,如果没有参数输入的话,返回 true。
  test 还可以用来比较数字的大小。例如:
[ $# -gt 0 ]  除此而外,还可以判断文件的类型。例如,我们想查找类型为符号链接的文件,然后删除。可以使用如下脚本:
# [ -h $HOME/bin ] &&rm $HOME/bin  其他常用的选项如下:

  •   -d:文件是否为目录
  •   -e:文件是否存在
  •   -x:文件是否可以执行
  •   -f:文件是否为常规文件
  •   -r:文件是否可读
  •   -p:文件是否为命名管道
  •   -b:文件是否为块设备文件
  •   -c:文件是否为字符设备文件
使用 if 条件判断语句
  if 语句的基本格式为:
if conditon ; then  
    statement 1
  
    statement 2fi
  我们可以看一个具体的例子:
#!/bin/bashif [ $# -lt 1 ] ; then  
    echo "Usage: $0 "
  
    exit 1fiecho "Hello $1"exit 0
  在运行此脚本时,如果没有输入参数,则提示正确的使用方法,非正常退出;否则,打印输入的参数,程序正常退出。
  if 语句还可以使用 else 条件分支。具体的语法为:
if conditon ; then  
    statementelse
  
    statementfi
  我们新建一个脚本文件 hello6.sh,来展示 if else 的用法。
#!/bin/bashif [ $# -lt 1 ] ; then  
    read -p "Enter a name: "
  
    name=$REPLYelse
  
    name=$1fiecho "Hello $name"exit 0
  当没有输入参数时,程序提示需要输入一个 name;如果输入了的话,就会打印出来。
  最后一种 if 的情况,也是最完整的 if 条件语句。语法如下;
if condition; then  
    statementelif condition; then
  
    statementelse
  
    statementfi
  再举个例子,新建脚本 backup2.sh,我们使用 tar 命令来备份压缩指定的目录,根据输入的参数“H”,“M”,“L”,可以执行不同的压缩级别。
  如果输入的参数为“H”,则使用 bzip2的压缩方式;
  如果输入的参数为“M”,则使用 gzip 的压缩方式;
  如果输入的参数为“L”,则使用 tar 命令对文件打包,不压缩。
#!/bin/bash# this sciprt dirs’ location are defualt under $HOMEread -p "Choose H, M or L compression " file_compressionread -p "Which directory do you want to backup to " dir_nameread -p "Which directory do you went to backup: " tobe_backup_name# The next lines creates the directory if it does not existtest -d $HOME/$dir_name || mkdir -m 700 $HOME/$dir_namebackup_dir=$HOME/$dir_nametar_l="-cvf  $backup_dir/b.tar $HOME/$tobe_backup_name"tar_m="-czvf $backup_dir/b.tar.gz $HOME/$tobe_backup_name"tar_h="-cjvf $backup_dir/b.tar.bzip2 $HOME/$tobe_backup_name"if [ $file_compression = "L" ] ; then  
    tar_opt=$tar_lelif [ $file_compression = "M" ]; then
  
    tar_opt=$tar_melse
  
    tar_opt=$tar_hfitar $tar_optexit 0
使用 case 选择语句
  如果 if else 分支太多的话,可以考虑使用 case 语句,case 语句提供了更加简洁的机制。
  case 语句的语法结构为:
case expression in  
    case1)
  
        statement1
  
        statement2
  
    ;;    case2)
  
        statement1
  
        statement2
  
   ;;
  
   *)
  
       statement1
  
   ;;esac
  还是举个简单的例子,新建脚本文件 grade.sh。
#!/bin/bash# Script to evaluate grades# Usage: grade.sh studentName gradeif [ ! $# -eq2 ] ; then  
    echo "You must provide  
  
    exit 2
  
fi
  

  
case $2 in
  
    [A-C]|[a-c])
  
        echo "$1 is a star pupil"
  
    ;;
  
    [Dd])
  
        echo "$1 needs to try a little harder!"
  
    ;;
  
    [E-F]|[e-f])
  
        echo "$1 could do a lot better next year"
  
    ;;
  
    *)
  
        echo "Grade could not be evaluated for $1"
  
esac
  

  
exit 0
  运行结果如下:
三. 一些注意事项
  我们前面已经介绍过 test 内置命令用来判断条件语句,但通常我们会推荐使用[]来替代 test 命令。例如:
[ -f /etc/hosts -a -r /etc/hosts ]  但这里面有个问题,例如,下面的脚本中,文件名中有空格,我们都知道,空格在命令行中有特殊的用处,用来分割命令选项和参数等。下面的代码会报错。
FILE="my file"[ -f $FILE -a -r $FILE ] && cat $FILE  报错信息为“too many arguments”,原因是程序把带有空格的文件名解析成了两部分。
  而这时,我们需要把变量用双引号包含起来,
FILE="my file"[ -f "$FILE" -a -r "$FILE" ] && cat "$FILE"  那有没有好的办法可以不使用双引号呢?当然有的,那就是使用“[[”关键字。
  “[[”并不是所有的 shell 都支持,它不兼容Bourne Shell。我们可以用 type 命令来查看它的类型。
  上面的脚本中的[]内的双引号就可以不用了,但要注意的是 cat 里的双引号还是要有的。
FILE="my file"[[ -f $FILE && -r $FILE ]] && cat "$FILE"  “[[”还有其他高级的功能:
1. 模式匹配
  例如,我们需要判断 Perl 脚本,然后做其他的操作,那么就可以这样写:
[[ $FILE = *.pl ]] && cp "$FILE" scripts/2. 正则表达式
  我们可以使用“=~”来匹配正则表达式。我们可以用正则表达式重写上面的脚本。
$ [[ $FILE =~ \.pl$ ]] &&cp "$FILE" scripts/  我们还可以使用“(())”运算符来做一些简单的运算。
1. 简单的数学运算
  我们可以使用“((”做一些简单的数学运算,它可以替代 let 这个内置命令。下面两行的代码执行结果是一样的。
a=(( 2 + 3 ))  
let a=2+3
2. 用在循环累加或累减中
  这种方式更加常用,
COUNT=1(( COUNT++ ))  
echo $COUNT
3. 用于运算检查中
  我们也可以把“((”用在 test 判断条件中,我们可以是用“>” 符号,来替代“-gt”。
(( COUNT > 1 )) && echo "Count is greater than 1"四. 迭代循环
  循环语句是任何一门语言都不能缺失的部分。shell 里也是一样,只是语法不太一样。如果学过其他的编程语言,就很容易掌握。
1. for 循环
  for 循环的语法疾结构为:
for f in * ; do  
    statement "$f"done
  这里的 f 就是迭代的元素,* 可以是一个数组或是 list,也可以是命令管道。
  还有另外一种写法:
for f in *  
do
  
    statement "$f"done
  可以根据自己的喜好选择一种写法。
  新建一个脚本文件,打印出所有输入的参数:
#!/bin/bashecho "You are using $(basename $0)"for n in $*do  
    echo "Hello $n"doneexit 0
  运行结果如下:
  在循环中,可以使用continue和break关键字,具体用法与其他语言里是一样的。continue表示在循环体内,跳过当前循环,执行下次的循环;而break表示退出整个循环,后面的循环和代码不再执行。
  看具体看例子。
$ for f in * ; do  
    [ -d "$f" ] || continue
  
         chmod 3777 "$f"done
  如果是目录,添加权限;如果不是,跳过当前循环,continue 后面代码不再执行,而是直接执行下次循环。
$ for f in * ; do  
    [ -d "$f" ] && breakdoneecho "We have found a directory $f"
  上面的脚本,在循环中一旦发现目录,则立即停止循环并退出。
2. while 循环
  while 循环可以说是 for 循环的一个变体,只要特定条件为真,while 语句就会执行。具体看例子,
COUNT=10while (( COUNT >= 0 )) ; do  
    echo -e "$COUNT \c"
  
    (( COUNT-- ))done ; echo
3. until 循环
  until循环与while语句的功能正好相反:只要特定条件为假,它就重复。下面是一个与前面的 while 循环具有同等功能的 until 循环。
COUNT=10  
until (( COUNT < 0 )) ; do
  
    echo -e "$COUNT \c"
  
    (( COUNT-- ))done ;
  

  
echo
4. 实例练习
  现在,我们做一个用户选择界面,这样,根据提示输入不同的参数来执行不同的功能,这里我们需要用到while循环,和前面讲过的case条件选择。
#!/bin/bashwhile true ; do  
    clear    echo "Choose an item: a, b or c"
  
    echo "a: Backup"
  
    echo "b: Display Calendar"
  
    echo "c: Exit"
  

  
    read -sn1        case "$REPLY" in
  
        a) tar -czvf $HOME/backup.tgz ${HOME}/JavaSource;;
  
        b) cal;;
  
        c) exit 0;;        esac
  
    read -n1 -p "Press andy key to continue"done
  根据提示,如果输入 a 的话,则把 home 目录下的 JavaSource 目录压缩打包。
  输入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-556020-1-1.html 上篇帖子: shell处理mysql增、删、改、查 下篇帖子: shell之路--Zabbix自动部署
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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