在linux shell中,通常我们将一些命令写在一个文件中就算是一个shell脚本了,但是如果需要执行更为复杂的逻辑判断,我们就需要使用流程控制语句来支持了。
所谓流程控制既是通过使用流程控制语句对程序流程的选择、循环、转向和返回等进行控制。流程控制是所有编程语言分重要组成部分,linux shell同样有一套自己的流程控制语句,其中主要包括条件语句(if),循环语(for,while),选择语句(case)。

条件选择if语句

单分支

if判断条件;then

      条件为真的分支代码

fi

双分支

if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi

多分支

if 判断条件1; then
条件为真的分支代码
elif 判断条件2; then
条件为真的分支代码
elif 判断条件3; then
条件为真的分支代码
else
以上条件都为假的分支代码
fi

逐个条件进行判断,第一次为“真”条件时,接着执行其分支,而后结束整个if语句

条件判断case语句

case 变量引用 in        #变量的引用加$
PAT1)
分支1
;;
PAT2)
分支2
;;
...
\*)
默认分支
;;
esac

case支持glob风格的通配符:
*: 任意长度任意字符
?: 任意单个字符
[]:指定范围内的任意单个字符
a|b: a或b

练习
、编写脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果
指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息

#!/bin/bash

read -p "please input username:" username
useradd $username &> /dev/null
if [ $? -eq 0 ];then
    echo "add $username user" && id $username
else
    echo "the user already exits"
fi

、编写脚本/root/bin/yesorno.sh,提示用户输入yes或no,并判断用户输入的
是yes还是no,或是其它信息

#!/bin/bash

read -p "Do you agree? yes or no: " ANS
if [ -z "$ANS" ] ;then
   echo "Please input yes or no"
   exit
fi
case $ANS in
[Yy]|[Yy][Ee][Ss])
   echo "Your answer is YES"
   ;;
[Nn]|[Nn][Oo])
   echo "Your answer is NO"
   ;;
*)
   echo "Your answer is fales"
esac

、编写脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型
(普通,目录,链接,其它文件类型)

#!/bin/bash

read -p "input file or dir:" choose
[ -z "$choose" ] && echo "Please input a file or dir"
if [ -d "$choose" ] ;then
   echo "$choose is directory"
elif [ -L "$choose" ] ;then
   echo "$choose is a link"
elif [ -f "$choose" ] ;then
   echo "$choose is a common file"
else
   echo "$choose is other type"
fi

、编写脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数

#!/bin/bash

read -p "input a digit:" NUM
if [[ "$NUM" =~ ^[0-9]+$ ]] ;then
   echo "$NUM is a int"
fi

循环

循环执行

将某代码段重复运行多次

重复运行多少次

循环次数事先已知

循环次数事先未知

有进入条件和退出条件

for, while, until

for循环

for 变量名 in 列表;

do

   循环体

done

执行机制:

    依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直 到列表中的元素耗尽,循环结束
列表生成方式:
() 直接给出列表
for num in ;do echo The number is $num ;done
The number is
The number is
The number is
The number is
The number is () 整数列表:
(a) {start..end}
for num in {....};do echo The numberis $num ;done
The numberis
The numberis
The numberis
The numberis
(b) $(seq [start [step]] end)
for num in `seq `;do echo The number is $num ;done
The number is
The number is
The number is () 返回列表的命令 $(COMMAND)
() 使用glob,如:*.sh
for num in "/root/bin/*.sh";do echo The filename is $num ;done
The filename is /root/bin/*.sh
(5) 变量引用; $@独立, $*整体(位置变量)

多行重定向

练习:
用for实现
、打印国际象棋
for i in {..};do
for j in {..};do
if [ $[i%] -eq ];then
echo -e "\033[1;41m \033[0m\e[1;43m \e[0m\c"
else
echo -e "\e[1;43m \e[0m\e[1;41m \e[0m\c"
fi
done
echo
done \c=-n默认不转行 \e \e[0m=\ \[0m颜色提示符 、添加10个用户user1-user10,密码为magedu
for i in {..};do
if id $i &> /dev/null ;then echo "user$i is exist"
else
useradd user$i &>/dev/null
echo "magedu" | passwd --stdin user$i &>/dev/null
echo "user $i add successful"
fi
done 注:批量删除用户for i in {..};do userdel -r(删除家目录) user$i;done 、/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的文件;分别读取每个文件,
以K开头的输出为文件加stop,以S开头的输出为文件名加start,如K34filename stop
S66filename start
#!/bin/bash
for i in $(ls /etc/rc.d/rc3.d/);do
if [[ $i =~ ^K.* ]];then
echo "$i stop"
elif [[ $i =~ ^S.* ]];then
echo "$i start"
fi
done
、编写脚本,提示输入正整数n的值,计算1++…+100的总和
#!/bin/bash declare -i sum= n=
for i in {..};do
let sum=sum+i | sum+=i
done
echo sum=$sum
unset sum
、计算100以内所有能被3整除的整数之和
#!/bin/bash
sum=
for i in {..};do
if [ $[$i%] -eq ];then
let sum+=$i
fi
done
echo $sum
、编写脚本,提示请输入网络地址,如192.168.0.0,判断输入的网段中主机在线状态
net=192.168.
for i in {..};do
{ if ping -c1 -w1 $net .$i &> /dev/null ;then
echo $net.$i is up
else
echo $net.$i is down
fi; } & 并行在后台执行
done
wait 、打印九九乘法表
#!/bin/bash for i in {..};do
for j in `seq $i`;do
result=$[$j*$i]
echo -e "$j*$i=$result \c"
done
echo
done 、在/testdir目录下创建10个html文件,文件名格式为数字N(从1到10)加随机8个字
母,如:1AbCdeFgH.html
取随机字母openssl rand -base64 | tr -dc '[:alpha:]' | head -c8
、打印等腰三角形
*的个数=line*-
空格=总line-
当前line
#!/bin/bash
read -p "Please input lines:" L
for i in `seq ${L}`;do
for (( j=${L};j>i;j-- ));do
echo -n " "
done
for j in `seq $i`;do
echo -n "*"
done
for (( n=;n<i;n++ ));do
echo -n "*"
done
echo " "
done

 打印等腰三角形并且颜色随机

#!/bin/bash
read -p "Please input lines:" L
for i in `seq ${L}`;do for j in `seq $[$L-i]`;do
echo -n " "
done
for k in `seq $[i*-]`;do
let color=$RANDOM%+
echo -ne "\e[1;5;${color}m*\e[0m"
done
echo
done

while循环

while 条件;do
循环体
done
条件(CONDITION):循环控制条件;进入循环之前,先做一次判断;每次循环之后会再次做判断;条件为"ture",
则执行一次循环;直到条件测试状态为“false”终止循环。 因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地 被修正 进入条件:CONDITION为true 退出条件:CONDITION为false
练习:
1、编写脚本,求100以内所有正奇数之和
#!/bin/bash
declare -i sum=
i=
while [ $i -le ];do
let sum=sum+i
let i=i+
done
echo sum=$sum 、编写脚本,提示请输入网络地址,如192.168.0.,判断输入的网段中主机
在线状态,并统计在线和离线主机各多少

#!/bin/bash

net=192.168.140
let num=1
x=0(up的主机)
y=0(down的主机数)
while [ ${num} -le 254 ];do
ping -c1 -w1 "${net}.${num}" &>/dev/null
  if [ $? -eq 0 ];then
    echo "${net}.${num} is up"
    x=$(($x+1))
  else
    echo "${net}.${num} is down"
    y=$(($y+1))
  fi
num=$(($num+1))
done
echo "total ${x} hosts are up"
echo "total ${y} hosts are down "

、编写脚本,打印九九乘法表

#!/bin/bash

declare -i i=1
while [ $i -le 9 ];do
    declare -i j=1
    while [ $j -le $i ];do
       result=$[$i*$j]
       echo -e "${j}x${i}=$result\t\c" \t是产生空格并对齐;\c是不换

let j++

done
    echo
    let i++
done

、编写脚本,利用变量RANDOM生成10个随机数字,输出这个数字,并显
示其中的最大值和最小值

#!/bin/bash

declare -i a=0
max=0
min=$RANDOM
while [ $a -le 9 ];do
num=$RANDOM
  if [ $num -le $max ];then
    if [ $num -le $min ];then
      min=$num
      fi
  else
      max=$num
  fi
  let a++:q!:
done
echo "the min number is $min,the max number is $max"

、编写脚本,实现打印国际象棋棋盘

#!/bin/bash

let i=0
while [ $i -le 15 ];do
  for ((j=0;j<4;j++));do
    if [ $[i%4] -eq 0 -o $[i%4] -eq 1 ];then
      echo -e "\033[1;41m \033[0m\033[1;47m \033[0m\c"
    else
      echo -e "\033[1;47m \033[0m\033[1;41m \033[0m\c"

    fi
  done
  echo
  let i++
done

、后续六个字符串:efbaf275cd、4be9c40b8b、44b2395c46、
f8c8873ce0、b902c16c8b、ad865d2f63是通过对随机数变量RANDOM随机
执行命令: echo $RANDOM|md5sum|cut –c1- 后的结果,请破解这些
字符串对应的RANDOM值while循环

 until循环

until CONDITION; do
循环体
done
进入条件: CONDITION 为false
退出条件: CONDITION 为true

循环控制语句continue

用于循环体中
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
continue
fi
CMDn
...
done

循环控制语句brek

用于循环体中
break [N]:提前结束第N层循环,最内层为第1层
while CONDTIITON1; do
CMD1
...
if CONDITION2; then
break
fi
CMDn
...
done

创建无限循环

while true; do

  循环体

done

until false; do

   循环体

Done

练习
、每隔3秒钟到系统上获取已经登录的用户的信息;如果发现用户hacker登录,
则将登录时间和主机记录于日志/var/log/login.log中,并退出脚本
#!/bin/bash

until `who | grep -o "^usr\b" &>/dev/null`;do
    sleep 3
done
echo "user is logining"
who | grep "user" >> /data/login.sh:q!

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

#!/bin/bash

i=$[$RANDOM%11]
while read -p "please input a number:" a;do
  [[ $a =~ ^[0-9]+$ ]] || { echo "please input a dight:1-10";continue; }
  if [ $i -gt $a ];then
    echo little
  elif [ $i -lt $a ];then
    echo more
  else
    echo right
    break
  fi
done

、用文件名做为参数,统计所有参数文件的总行数

if [ $# -eq 0 ];then  $#是所有未知变量
  echo "please input file path"
 else
  until [ -z "$1" ];do -z判断文件是否为空
    echo "tongji file:$1"
    echo "the file total line are: `wc -l $1 | cut -d " " -f1`“
    echo
    shift
done
echo "finish"
fi

、用二个以上的数字为参数,显示其中的最大值和最小值

函数:function

是由若干条shell命令组成的语句块,实现代码重用和模块化编程;函数只有被调用才会执行

语法1:

function func_name {

  函数体

}

语法2::

func_name() {

  函数体

}

注意:函数中变量的生效范围是当前所在shell

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

函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现它后才能使用,调用函数时就像使用命令一样调用

return #:在函数中使用,跳出函数,返回值 #;如果没有定义退出返回值则函数的默认返回值为函数中最后一条命令的返回值

local var:声明函数为本地变量,只在函数内部生效

declare

  -f func_name 查看指定函数

  -xf func_name 声明函数的生效范围为全局 == export -f func_name

  -i 声明变量为数字

  -g 在函数中使用,声明变量为普通变量

  declare 在函数中用隐式使用了local,定义的变量为本地变量

函数的递归调用:在函数中调用函数本身

fork炸弹

bome() { bome|bome& }; bome

编写脚本copycmd.sh

  • (1) 提示用户输入一个可执行命令名称;
  • (2) 获取此命令所依赖到的所有库文件列表;
  • (3) 复制命令至某目标目录(例如/mnt/sysroot)下的对应路径下;
    • 如:/bin/bash ==> /mnt/sysroot/bin/bash
  • (4) 复制此命令依赖到的所有库文件至目标目录下的对应路径下;(5)每次复制完成一个命令后,不要退出,而是提示用户键入新的要复制的命令,并重复完成上述功能;直到用户输入quit退出;
    • 如:/lib64/ld-linux-x86-64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2
#!/bin/bash
. my_functions
Ddir="/mnt/sysroot"
[ ! -d "$Ddir" ] && mkdir "$Ddir" cpbin() {
cmddir=`echo "$Cmd_path" |grep -o ".*/\b"`
[ ! -d "${Ddir}${cmddir}" ] && mkdir -p "${Ddir}${cmddir}"
cp -n "$Cmd_path" "${Ddir}${cmddir}"
} libcp() {
echo "$Lib_path" |while read line ;do
libdir=`echo "$line" |grep -o ".*/\b"`
[ ! -d "${Ddir}${libdir}" ] && mkdir -p "${Ddir}${libdir}"
cp -n "$line" "${Ddir}${libdir}" 2>/dev/null
done
} while read -p "Input a cmd. (quit): " CMD ;do
if [ "$CMD" == 'quit' ] ;then echo "Think you! Bye bye."; break; fi
if ! which "$CMD" &>/dev/null ;then
echo "not find $CMD, please input again."
failed "copy $CMD failed."
continue
fi
Cmd_path=`which $CMD |grep -o "/.*"`
Lib_path=`ldd $Cmd_path |sed -nr 's#.*[[:space:]]+(/.*) .*#\1#p'`
cpbin
libcp
success "copy $CMD Complete."
done

求斐波那契数列的第N个数

#!/bin/bash
feibo() {
if [ $1 -eq 0 ] ; then
echo 0
elif [ $1 -eq 1 ] ;then
echo 1
else
echo $[`feibo $[$1-1]`+`feibo $[$1-2]`]
fi
} read -p "please a num: " n

求N的阶乘

#!/bin/bash
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ] ;then
echo 1
else
echo $[$1*`fact $[$1-1]`]
fi
} fact $1

shell脚本编程进阶的更多相关文章

  1. Shell—脚本编程进阶

    shell脚本进阶之条件语句 条件选择if语句 https://www.runoob.com/?s=shell&page=1 https://www.cnblogs.com/flylinux/ ...

  2. shell脚本编程进阶及RAID和LVM应用1

    bash脚本编程 脚本文件格式: 第一行,顶格写: #!/bin/bash 注释行:#开头 代码注释:写清楚注释 规范写脚本:适度缩进,添加空白行 编程语言:有编程语法格式,库,算法和数据结构 编程思 ...

  3. shell脚本编程进阶及RAID和LVM应用2

    文件测试 存在性测试 -a FILE 这个选项的效果与-e 相同.但是它已经被弃用了,并且不鼓励使用 -e FILE 文件的存在性测试,存在则为真,否则为假 例:~]# [ -e /etc/rc.d/ ...

  4. 《Linux命令行与shell脚本编程大全》 第二十七章 学习笔记

    第二十七章:shell脚本编程进阶 监测系统统计数据 系统快照报告 1.运行时间 uptime命令会提供以下基本信息: 当前时间 系统运行的天数,小时数,分钟数 当前登录到系统的用户数 1分钟,5分钟 ...

  5. 《Linux命令行与shell脚本编程大全 第3版》

    第一部分 Linux 命令行 第1章  初识Linux she1.1   什么是Linux 21.1.1 深入探究Linux 内核 31.1.2 GNU 工具 61.1.3 Linux 桌面环境 81 ...

  6. Shell脚本编程30分钟入门

    Shell脚本编程30分钟入门 转载地址: Shell脚本编程30分钟入门 什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd ~ mkdir shell_tut cd shell_t ...

  7. Linux shell脚本编程(三)

    Linux shell脚本编程 流程控制: 循环语句:for,while,until while循环: while CONDITION; do 循环体 done 进入条件:当CONDITION为“真” ...

  8. Linux shell脚本编程(二)

    Linux shell脚本编程(二) 练习:求100以内所有偶数之和; 使用至少三种方法实现; 示例1: #!/bin/bash # declare -i sum=0 #声明一个变量求和,初始值为0 ...

  9. Linux shell脚本编程(一)

    Linux shell脚本编程: 守护进程,服务进程:启动?开机时自动启动: 交互式进程:shell应用程序 广义:GUI,CLI GUI: CLI: 词法分析:命令,选项,参数 内建命令: 外部命令 ...

随机推荐

  1. windows下Jmeter压测端口占用问题(亲测有效)

    windows下Jmeter压测端口占用问题 1 报错信息描述 压测的初期,在设置了 150qps/s 的并发数下压测几分钟后 Jmeter 就出现了如下报错. JAVA.NET.BINDEXCEPT ...

  2. Springboot整合MybatisPlus

    目录 1.pom文件 2.创建CodeGenerator.java 3.在application.yml中配置mybatis-plus 4.创建MybatisPlusConfig.java文件 其他 ...

  3. VIM从原理上认识^M问题

    问题背景 VIM在打开文件的时候如果遇到两种换行符风格(dos与unix)共存的文件,通常会在行尾显示出烦人的^M.如果^M较少,比较容易定位到哪几行出了问题,但是如果^M较多,就很难搞.下面先给出解 ...

  4. Java检查异常和非检查异常,运行时异常和非运行时异常的区别

    通常,Java的异常(包括Exception和Error)分为检查异常(checked exceptions)和非检查的异常(unchecked exceptions).其中根据Exception异常 ...

  5. Django 开发相关知识 整理

    前言 前端ajax HTTP请求头 ajax上传文件 jsonp跨域 URL 设计 分发 url参数编码 反向生成url 视图 request对象 POST url信息 视图返回值 HttpRespo ...

  6. RabbitMQ 功能

    学习完了rabbitmq总一下 RabbitMQ依赖的语言 erlang 第一它可以实现不同程序之间的程序信息储存交互,在易用性.扩展性.高可用性的方面不俗. rabbitmq相当于一个中间人,我们同 ...

  7. 《浏览器工作原理与实践》<04>从输入URL到页面展示,这中间发生了什么?

    “在浏览器里,从输入 URL 到页面展示,这中间发生了什么? ”这是一道经典的面试题,能比较全面地考察应聘者知识的掌握程度,其中涉及到了网络.操作系统.Web 等一系列的知识. 在面试应聘者时也必问这 ...

  8. Kubernetes对象中的PersistentVolume、PersistentVolumeClaim和StorageClass的概念关系

    Kubernetes容器要持久化数据,离不开volume,k8s的volume和Docker原生概念中的volume有一些差别,不过本次不讲这个,本次要明确的是k8s持久化数据用到的几个对象Persi ...

  9. seaborn图形

    kdeplot(核密度估计图) 核密度估计(kernel density estimation)是在概率论中用来估计未知的密度函数,属于非参数检验方法之一.通过核密度估计图可以比较直观的看出数据样本本 ...

  10. 自己手写实现Dubbo

    目录 dubbo 简单介绍 为什么手写实现一下bubbo? 什么是RPC? 接口抽象 服务端实现 注册中心 消费者端: dubbo 简单介绍 dubbo 是阿里巴巴开源的一款分布式rpc框架. 为什么 ...