前言:
目前同学们对“nginx shell”大概比较着重,咱们都想要剖析一些“nginx shell”的相关知识。那么小编同时在网摘上搜集了一些关于“nginx shell””的相关内容,希望兄弟们能喜欢,小伙伴们一起来学习一下吧!续接上回。。。
4 流程控制
4.1 条件选择
4.1.1 条件判断分绍
4.1.1.1 单分支条件
4.1.1.2 多分支条件
4.1.2 选择执行 if 语句
格式:
if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi
单分支
if 判断条件;then 条件为真的分支代码fi
双分支
if 判断条件; then 条件为真的分支代码else 条件为假的分支代码fi
多分支
if 判断条件1; then 条件1为真的分支代码elif 判断条件2; then 条件2为真的分支代码elif 判断条件3; then 条件3为真的分支代码...else 以上条件都为假的分支代码fi
说明:
多个条件时,逐个条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句if 语句可嵌套
案例:
#根据命令的退出状态来执行命令if ping -c1 -W2 station1 &> /dev/null; then echo 'station1 is UP' elif grep -q 'station1' ~/maintenance.txt; then echo 'station1 is undergoing maintenance'else echo 'station1 is unexpectedly DOWN!' exit 1fi
脚本案例:身体质量指数
[root@nginx ~]#cat if_bmi.sh #!/bin/bash read -p "请输入身高(m为单位): " HIGHif [[ ! "$HIGH" =~ ^[0-2](\.[0-9]{,2})?$ ]];then echo "输入错误的身高" exit 1firead -p "请输入体重(kg为单位): " WEIGHTif [[ ! "$WEIGHT" =~ ^[0-9]{1,3}$ ]];then echo "输入错误的体重"; exit 1; fiBMI=`echo $WEIGHT/$HIGH^2|bc`if [ $BMI -le 18 ] ;then echo "太瘦了,多吃点"elif [ $BMI -lt 24 ] ;then echo "身材很棒!"else echo "太胖了,注意节食,加强运动"fi
4.1.3 条件判断 case 语句
格式:
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
case 变量引用 inPAT1) 分支1 ;;PAT2) 分支2 ;;...*) 默认分支 ;;esac
case支持glob风格的通配符:
* 任意长度任意字符? 任意单个字符[] 指定范围内的任意单个字符| 或者,如: a|b
案例:
[root@nginx ~]#cat case_yesorno.sh#!/bin/bashread -p "Do you agree(yes/no)? " INPUTINPUT=`echo $INPUT | tr 'A-Z' 'a-z'` case $INPUT iny|yes) echo "You input is YES" ;;n|no) echo "You input is NO" ;;*) echo "Input fales,please input yes or no!"esac
案例:
[root@nginx ~]#cat case_yesorno2.sh #!/bin/bash read -p "Do you agree(yes/no)? " INPUTcase $INPUT in[yY]|[Yy][Ee][Ss]) echo "You input is YES" ;;[Nn]|[Nn][Oo]) echo "You input is NO" ;;*) echo "Input fales,please input yes or no!" esac
案例:文件后缀处理
[root@nginx ~]#cat suffix.sh #!/bin/bash read -p "please input a file: " FILESUFFIX=`echo $FILE | grep -Eo "[^.]+$"`case $SUFFIX ingz) echo gzip ;;bz2) echo bzip2 ;;xz) echo xz ;;Z) echo compress ;;zip) echo zip ;;*) echo other ;;esac
案例:运维菜单
[root@nginx ~]#cat work_menu.sh #!/bin/bash echo -en "\E[$[RANDOM%7+31];1m"cat <<EOF请选择:1)备份数据库2)清理日志3)软件升级4)软件回滚5)删库跑路EOFecho -en '\E[0m'read -p "请输入上面数字1-5: " MENUcase $MENU in1) echo "执行备份数据库" #./backup.sh ;;2) echo "清理日志" ;;3) echo "软件升级" ;;4) echo "软件回滚" ;;5) echo "删库跑路" ;;*) echo "INPUT FALSE!"esac
4.2 循环
4.2.1 循环执行介绍
将某代码段重复运行多次,通常有进入循环的条件和退出循环的条件
重复运行次数
循环次数事先已知循环次数事先未知
常见的循环的命令:for, while, until
4.2.2 循环 for
[root@nginx ~]# help forfor: for 名称 [in 词语 ... ] ; do 命令; done 为列表中的每个成员执行命令。 `for' 循环为列表中的每个成员执行一系列的命令。如果没有 `in WORDS ...;'则假定使用 `in "$@"'。对于 WORDS 中的每 个元素,NAME 被设定为该元素,并且执行 COMMANDS 命令。 退出状态: 返回最后执行的命令的状态。for ((: for (( 表达式1; 表达式2; 表达式3 )); do 命令; done 算术 for 循环。 等价于 (( EXP1 )) while (( EXP2 )); do COMMANDS (( EXP3 )) done EXP1、EXP2 和 EXP3都是算术表达式。如果省略任何表达式, 则等同于使用了估值为1的表达式。 退出状态: 返回最后执行的命令的状态。[root@nginx ~]#
格式1:
for NAME [in WORDS ... ] ; do COMMANDS; done#方式1for 变量名 in 列表;do 循环体done#方式2for 变量名 in 列表do 循环体done
执行机制:
依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束如果省略 [in WORDS ... ] ,此时使用位置参量
for 循环列表生成方式:
直接给出列表整数列表:
{start..end}$(seq [start [step]] end)返回列表的命令:
$(COMMAND)使用glob,如:*.sh变量引用,如:$@,$*,$#
案例:计算1+2+3+...+100 的结果
[root@nginx ~]# sum=0;for i in {1..100};do let sum+=i;done ;echo sum=$sumsum=5050[root@nginx ~]#[root@nginx ~]#seq -s+ 100|bc50505050[root@nginx ~]#echo {1..100}|tr ' ' +|bc5050[root@nginx ~]#seq 100|paste -sd +|bc5050
案例:100以内的奇数之和
[root@nginx ~]#sum=0;for i in {1..100..2};do let sum+=i;done;echo sum=$sumsum=2500[root@nginx ~]#seq -s+ 1 2 100| bc2500[root@nginx ~]#echo {1..100..2}|tr ' ' + | bc2500
案例:
[root@nginx ~]#cat for_sum.sh #!/bin/bash sum=0for i in $* ; do let sum+=idoneecho sum=$sum [root@nginx ~]#sh for_sum.sh 1 2 3 4 5 6sum=21
案例:批量创建用户和并设置随机密码
[root@nginx ~]#cat user_for.sh #!/bin/bash for i in {1..10};do useradd user$i PASS=`cat /dev/urandom | tr -dc '[:alnum:]' |head -c12` echo $PASS | passwd --stdin user$i &> /dev/null echo user$i:$PASS >> /tmp/user.log echo "user$i is created"done
案例:九九乘法表
[root@nginx ~]#cat 9x9_for.sh#!/bin/bash for i in {1..9};do for j in `seq $i`;do echo -e "${j}x${i}=$[j*i]\t\c" done echodone
案例:将指定目录下的文件所有文件的后缀改名为 bak 后缀
[root@nginx ~]#cat for_rename.sh #!/bin/bash DIR=/tmp/testcd $DIRfor FILE in * ;do PRE=`echo $FILE|grep -Eo ".*\."` mv $FILE ${PRE}bak# PRE=`echo $FILE|rev|cut -d. -f 2-|rev`# PRE=`echo $FILE | sed -nr 's/(.*)\.([^.]+)$/\1/p'# SUFFIX=`echo $FILE | sed -nr 's/(.*)\.([^.]+)$/\2/p'`# mv $FILE $PRE.bakdone
案例:要求将目录YYYY-MM-DD/中所有文件,移动到YYYY-MM/DD/下
#1.创建YYYY-MM-DD格式的目录,当前日期一年前365天到目前共365个目录,里面有10个文件.log后缀的文件[root@nginx ~]#cat for_dir.sh #!/bin/bashfor i in {1..365};do DIR=`date -d "-$i day" +%F` mkdir -pv /tmp/test/$DIRcd /tmp/test/$DIRfor n in {1..10};do touch $RANDOM.log donedone#2.将上面的目录移动到YYYY-MM/DD/下 #!/bin/bash#DIR=/tmp/testcd $DIRfor subdir in * ;do YYYY_MM=`echo $subdir |cut -d"-" -f1,2` DD=`echo $subdir |cut -d"-" -f3` [ -d $YYYY_MM/$DD ] || mkdir -p $YYYY_MM/$DD &> /dev/null mv $subdir/* $YYYY_MM/$DDdonerm -rf $DIR/*-*-*
格式2
双小括号方法,即((…))格式,也可以用于算术运算,双小括号方法也可以使bash Shell实现C语言风格的变量操作 : I=10;((I++))
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; donefor ((控制变量初始化;条件判断表达式;控制变量的修正表达式))do 循环体done
说明:
控制变量初始化:仅在运行到循环代码段时执行一次控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断
案例:
#!/bin/bashfor((sum=0,i=1;i<=100;sum+=i,i++));do truedoneecho $sum
案例:九九乘法表
#!/bin/bash#语法1实现for i in {1..9};do for j in `seq $i`;do echo -e "${j}x$i=$((j*i))\t\c" done echodone#语法2实现for((i=1;i<10;i++));do for((j=1;j<=i;j++));do echo -e "${j}x$i=$((j*i))\t\c" done echodone
案例:等腰三角形
[root@nginx ~]#cat for_triangle.sh#!/bin/bashread -p "请输入三角形的行数: " linefor((i=1;i<=line;i++));do for((k=0;k<=line-i;k++));do echo -e ' \c' done for((j=1;j<=2*i-1;j++));do echo -e '*\c' done echodone[root@nginx ~]#bash for_triangle.sh请输入三角形的行数: 10 * *** ***** ******* ********* *********** ************* *************** ***************** *******************
案例:生成进度
[root@nginx ~]# for ((i = 0; i <= 100; ++i)); do printf "\e[4D%3d%%" $i;sleep 0.1s; done100% [root@nginx ~]#
4.2.3 循环 while
格式:
while COMMANDS; do COMMANDS; donewhile CONDITION; do 循环体done
说明:
CONDITION:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“true”,则执行一次循环;直到条件测试状态为“false”终止循环,因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正
进入条件:CONDITION为true退出条件:CONDITION为false
无限循环
while true; do 循环体donewhile : ; do 循环体done
案例:
[root@nginx ~]#sum=0;i=1;while ((i<=100));do let sum+=i;let i++;done;echo $sum5050
4.2.4 循环 until
格式:
until COMMANDS; do COMMANDS; doneuntil CONDITION; do 循环体done
说明:
进入条件: CONDITION 为false
退出条件: CONDITION 为true
案例:
[root@nginx ~]#sum=0;i=1;until ((i>100));do let sum+=i;let i++;done;echo $sum5050
无限循环
until false; do 循环体Done
4.2.4 循环控制语句 continue
continue [N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
格式:
while CONDITION1; do CMD1 ... if CONDITION2; then continue fi CMDn ...done
案例:
[root@nginx ~]#cat continue_for.sh#!/bin/bashfor ((i=0;i<10;i++));do for((j=0;j<10;j++));do [ $j -eq 5 ] && continue 2 echo $j done echo ---------------------------done
4.2.5 循环控制语句 break
break [N]:提前结束第N层整个循环,最内层为第1层
格式:
while CONDITION1; do CMD1 ... if CONDITION2; then break fi CMDn ...done
案例:
[root@nginx ~]#cat break_for.sh #!/bin/bash for ((i=0;i<10;i++));do for((j=0;j<10;j++));do [ $j -eq 5 ] && break echo $j done echo ---------------------------done
[root@nginx ~]#cat break_for.sh#!/bin/bashfor ((i=0;i<10;i++));do for((j=0;j<10;j++));do [ $j -eq 5 ] && break 2 echo $j done echo ---------------------------done[root@nginx ~]#bash break_for.sh01234
[root@nginx ~]#cat guess.sh#!/bin/bashNUM=$[RANDOM%10]while read -p "输入 0-9 之间的数字: " INPUT ;do if [ $INPUT -eq $NUM ];then echo "恭喜你猜对了!" break elif [ $INPUT -gt $NUM ];then echo "数字太大了,重新猜!" else echo "数字太小了,重新猜!" fidone
4.2.6 循环控制 shift 命令
shift [n] 用于将参量列表 list 左移指定次数,缺省为左移一次。
参量列表 list 一旦被移动,最左端的那个参数就从列表中删除。while 循环遍历位置参量列表时,常用到 shift
案例:doit.sh
[root@nginx ~]#cat doit.sh#!/bin/bash# Name: doit.sh# Purpose: shift through command line arguments# Usage: doit.sh [args]while [ $You can't use 'macro parameter character #' in math mode# -gt 0 ] # or (( $# > 0 ))do echo $* shiftdone./doit.sh a b c d e f g h
案例:
[root@nginx ~]#cat shift.sh#!/bin/bash#step through all the positional parametersuntil [ -z "$1" ] do echo "$1" shiftdoneecho ./shfit.sh a b c d e f g h
案例:
[root@nginx ~]#cat shift_batch_user.sh #!/bin/bashif [ $# -eq 0 ];then echo "Usage: `basename $0` user1 user2 ..." exitfi while [ "$1" ];do if id $1 &> /dev/null;then echo $1 is exist else useradd $1 echo "$1 is created" fi shiftdoneecho "All user is created"[root@nginx ~]#sh shift_batch_user.shUsage: shift_batch_user.sh user1 user2 ... [root@nginx ~]#sh shift_batch_user.sh t1 a1 j1t1 is exista1 is existj1 is createdAll user is created
4.2.7 while 特殊用法 while read
while 循环的特殊用法,遍历文件或文本的每一行
格式:
while read line; do 循环体done < /PATH/FROM/SOMEFILE
说明:依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line
案例:
[root@nginx ~]# echo test | read X ; echo $X[root@nginx ~]#[root@nginx ~]# echo test | read X ; echo $X[root@nginx ~]# echo test | while read X ; do echo $X;donetest[root@nginx ~]# echo test | { read X ; echo $X; }test[root@nginx ~]# echo test | ( read X ; echo $X )test[root@nginx ~]# echo zhangsan lisi wangwu | ( read X Y Z; echo $X $Y $Z )zhangsan lisi wangwu[root@nginx ~]# echo zhangsan lisi wangwu | while read X Y Z; do echo $X $Y $Z;donezhangsan lisi wangwu[root@nginx ~]#
[root@nginx ~]#cat while_read_diskcheck.sh#!/bin/bashWARNING=80MAIL= #输入你的邮箱df |sed -nr "/^\/dev\/sd/s#^([^ ]+) .* ([0-9]+)%.*#\1 \2#p"|while read DEVICE USE;do if [ $USE -gt $WARNING ] ;then echo "$DEVICE will be full,use:$USE" | mail -s "DISK WARNING" $MAIL fidone
案例:查看/sbin/nologin的shell类型的用户名和UID
[root@nginx ~]#cat while_read_passwd.sh#!/bin/bashwhile read line ;do if [[ "$line" =~ /sbin/nologin$ ]] ;then echo $line | cut -d: -f1,3 fi done < /etc/passwd
4.2.8 循环与菜单 select
格式:
select NAME [in WORDS ... ;] do COMMANDS; doneselect variable in list ;do 循环体命令done
说明:
select 循环主要用于创建菜单,按数字顺序排列的菜单项显示在标准错误上,并显示 PS3 提示符,等待用户输入用户输入菜单列表中的某个数字,执行相应的命令用户输入被保存在内置变量 REPLY 中select 是个无限循环,因此要用 break 命令退出循环,或用 exit 命令终止脚本。也可以按 ctrl+c 退出循环select 经常和 case 联合使用与 for 循环类似,可以省略 in list,此时使用位置参量
案例:
[root@nginx ~]#cat select.sh #!/bin/bash#sum=0PS3="请点菜(1-6): "select MENU in 烤鸭 烧鸡 小龙虾 鲍鱼 鱼翅 点菜结束;docase $REPLY in1) echo $MENU 价格是 100 let sum+=100 ;;2) echo $MENU 价格是 88 let sum+=88 ;;3)echo $MENU价格是 66 let sum+=66 ;;4) echo $MENU 价格是 166 let sum+=166 ;;5) echo $MENU 价格是 200 let sum+=200 ;;6) echo "点菜结束,退出" break ;;*) echo "点菜错误,重新选择" ;;esacdoneecho "总价格是: $sum"
未完待续~~
标签: #nginx shell