• Linux shell脚本进阶使用


    shell的循环控制语句

    -  continue:提前结束某次循环,重新开始下一次
    
    -  break:提前结束某层循环
    

    范例:

    #求100以内的奇数和
    #!/bin/bash
    sum=0
    for i in `seq 100`;do
      if [ $[i%2] -ne 0 ];then
      	continue
           else
                  let sum+=$i
           fi
    done
    echo $sum
    
    #实现100以内的奇数和
    #!/bin/bash
    sum=0
    for i in `seq 100`;do  #``:命令替换
       if [ $[i%2] -eq 0 ];then  #$[]:shell的算数语法
             let sum+=$i #let工具需要借助一个变量存储计算后的值
            fi
    done
    
    echo $sum
    
    

    shell的循环控制 shift 命令

    每执行一次shift命令,都会左移一次。

    #比如有三个参数$1 $2 $3,执行一次shift命令后,$1就删除了,$2变成$1,一次类推。
    #!/bin/bash
    echo $*
    shift
    echo $*
    shift
    echo $*
    shift
    #输出结果:
    [root@Centos8 ~]# bash shift.sh 1 2 3 4 5
    1 2 3 4 5
    2 3 4 5
    3 4 5
    
    #利用shift的方式批量创建账号
    #!/bin/bash
    
    if [$# -eq 0];then  #判断位置参数是否是0
    	echo "请输入需要创建的用户"
    	exit
    fi
    
    while [ "$1"  ] ;do #[ "$1"  ]:判断$1是否为空,只写字符串就表示字符串不为空,为真
    	if id $1 &> /dev/null; then  #如果id命令执行的结果为真($?=0)就表示用户存在了
    		echo "$1 is exist"
    	else
    		useradd $1
    		echo "$1 is create"
    	fi
    	shift
    done
    echo "all user is create "
    
    #使用for的形式创建账号
    if [$# -eq 0];then  #判断位置参数是否是0
    	echo "请输入需要创建的用户"
    	exit
    fi
    
    for user in $*;do
    if id $user &> /dev/null; then  #如果id命令执行的结果为真($?=0)就表示用户存在了
    		echo "$user is exist"
    	else
    		useradd $user
    		echo "$user is create"
    	fi
    done
    echo "all user is create "
    
    折叠

    while 特殊用法 while read

    文本的逐行处理。

    格式

    while read line; do
     循环体
    done < /PATH/FROM/SOMEFILE
    
    while read line ;do echo $line; done #标准输入,逐行处理
    
    while read line ; do xxxx; done < filename #可以利用标准输入重定向把文件传给它
    
    cat /etc/issue | while read line ;do echo $line; done #用管道
    
    #使用while read判断磁盘分区磁盘的利用率
    #!/bin/bash
    
    while true ; do #一直执行
       df | sed -nr '/^\/dev\/sd/ s#([^ ]+).*([0-9]+)%.*#\1 \2#p' | while read  DEV USE;do 
       if [ $USE -gt 80 ];then 
    	 echo "$DEV will be full, USE: $USE"
       else
    	 echo "$DEV is health, USE: $USE"
       fi
       done
    sleep 2 #每两秒执行一次
    done
    
    #sed -nr '/^\/dev\/sd/ s#(^[^ ]+).*([0-9]+)%.*#\1 \2#p' | while read  DEV USE;do
    #/^\/dev\/sd/ --- 以为/dev/sd开头的(非空格的内容)
    #[^ ]+ :取出分区的设备,非空格,一个以上的字符
    #\1 \2 --- 后项替换
    
    #查看/sbin/nologin的shell类型的用户名和UID
    #!/bin/bash
    while read line ; do #通过输入重定向的方式逐行处理内容
    	if [[ $line =~ /sbin/nologin$  ]];then # [[ =~ ]]:会把会把右边的字符串当成正则
    		echo $line | cut -d: -f1,3 # -d:指定分隔符 -f:取那几列
            fi
    done < /etc/passwd
    
    
    

    循环与菜单 select

    帮助我们生成菜单的作用。

    格式:

    #语法和for的语法很类似
    select 变量 in 列表 ;do
    	所作的操作
    done
    
    #PS3用于输出提示信息,效果等同于 read -p
    #输入的信息保存到置变量REPLY中
    #select 是个无限循环,因此要用 break 命令退出循环
    
    #PS1:是影响我们当前提符的
    #PS2:影响多行多定向(<<)提示符的 echo $PS2--> >
    
    #列表就是用来生成菜单的
    PS3="请选择功能(1-5):" #PS3:更改菜单的提示信息
    select list in 升级软件 备份数据库 回滚软件 删库跑路 ; do
    	echo $REPLY;
    done
    
    #!/bin/bash
    
    PS3="请输入对应选项(1-5): "
    
    select menu in 安装 升级 配置 卸载;do
           case $REPLY in 
           1)
    	       echo "install"
    	       ;;
           2)
    	       echo "update"
    	       ;;
           3)
    	       echo "config"
    	       ;;
           4)
    	       echo "remove"
    	       ;;
           *)
    	       echo "No this select"
    	       ;;
            esac
    done
    
    

    函数:function

    函数定义格式:

    函数名 ()
    {
     	函数体
    }
    或
    function 函数
    {
    	函数体
    }
    #写了function关键词,可以省略函数名后面的括号
    

    调用函数:直接通过函数名调用

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

    [root@centos8 ~]#dir() {
    > ls -l
    > }
    [root@centos8 ~]#dir  #调用函数
    total 4
    

    函数文件:只存放函数的文件

    调用函数文件
     . filename 或 source  filename #.和source等价
    

    函数返回值

    # 使用echo等命令进行输出
    
    # 函数体中调用命令的输出结果
    

    函数的参数

    也是用$n等来实现的。

    函数退出状态码

    #1. 取决于最后一天命令的状态码
    
    #2. 自定义状态码: retuen num #0:无错误返回,1-255:有错误返回
    

    函数的变量

    普通变量:变量名="值" #只能当前进程使用
    
    环境变量:export 变量名="值" #当前进程和子进程都能使用
    
    本地变量: local 变量名="值" #限定了变量在函数中有效,对外部的不影响
    

    范例:

    #判断操作系统类型安装软件
    #!/bin/bash
    os_type
    {
    if   cat /etc/os-release | grep -i -q "ubuntu" ; then  # -q:不显示查找的结果,不管找到与否
    	echo "ubuntu"
    elif  cat /etc/os-release | grep -E "centos" ;then
    	echo "centos"
    else 
    	echo "no find ubuntu or centos"
    fi
    }
    if [ `os_type` = centos ] ;then #字符串用= != < > 等 (判断符号两边需要加上空格)
    	yum install httpd -y
    elif [ `os_type` = ubuntu ] ; then
    	apt install httpd -y
    else
    	echo "nofind centos or ubuntu"
    
    #粗略判断ip格式是否合法
    ##/bin/bash
    is_ip () 
    { 
       if	[[ "$1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$  ]] ;then
    	  echo "$1 is valid"
       else
    	  echo "$1 is not valid" 
      fi
    }
    is_ip $1  #给函数传递参数
    

    shell脚本的常用工具

    shell脚本信号的捕捉:trap

    trap:陷阱,用于捕获信号的

    信号的类型:

    使用trap -l可以查看

    CTRL+C:发送的就是2(SIGINT)信号,程序收到这个信号以后就会退出。
    

    shell脚本捕获信号

    通过trap指令来完成:

    #格式:
    #通过捕获信号来修改信号的原有功能
    trap '捕获到信号以后要做的事'  信号 #信号可以是全称、缩写或者前面的数字标号
    
    例如:
    trap '' 信号 #忽略信号操作
    trap '-' 信号 #恢复信号原有的功能
    

    shell脚本创建临时文件:mktemp

    希望创建的临时文件和现有文件不冲突
    
    #创建临时文件的格式
    mktemp [选项] [模板]  #模板就是临时文件的文件名
    #模板格式: filenameXXX,文件前缀+三个随机字符(X(大写)至少要出现三个)
    
    例如;mktemp fileXXX --->file90X
    #选项: 
    
    -d:创建临时目录文件
    -p:指定创建的位置
    

    范例

    #通过创建临时文件,实现文件垃圾箱(把不用的文件移动到一个目录里面)
    DIR=`mktemp -d /tmp/trash-$(date +%F_%H-%M-%S)XXXXXX` #创建一个临时目录文件
    mv $* $DIR # $*:表示所有位置的参数
    echo $* is move to $DIR
    

    安装复制文件 install

    install命令可以改权限、拷贝、创建文件夹等

    #编译安装make install:把make命令执行的编译的结果复制到对应的文件中。make install 调用了install命令
    #install 的用法(和cp命令很类似)
    
    #选项
    -m MODE,默认755,修改权限
    -o OWNER,指定所有者
    -g GROUP,指定所有组
    -d DIRNAME 目录,创建目录文件
    
    ##例如
    install -m 770 -d /testdir/installdir #创建一个权限为770的文件夹(install -d 相当于 mkdir -p)
    
    install -m 700 -o tom -g root /etc/issue /etc/xx.txt #复制一个文件到指定位置,复制的时候更改了权限
    

    expect

    把交互式的命令变成非交互式的。(espect通过对指定命令的监控,出现对应关键字的时候执行对应操作)

    #expect中相关命令:
    spawn 监控某一个命令的执行
    expect 捕获特定的字符串
    send  捕获到这个特定字符串后,发送对应信息
    interact 允许用户交互
    exp_continue 匹配多个字符串在执行动作后加此命令
    

    范例

    #匹配到hi后,会输出“you said hi”,并换行
     expect "hi" {send "You said hi\n"} #捕获屏幕上是否有hi,如果有就自动打印xx
    

    shell脚本的数组

    数组:多个变量的集合

    bash的数组支持稀疏格式 #索引不连续就叫做稀疏格式
    

    数据的申明

    建议先声明再使用。
    #声明数组:
    declare -a 数据名 #申明为普通数组
    declare -A 数组名 #申明为关联数组 #管理数组必须申明后再使用,且关联和普通不能转换
    
    #声明变量
    既然所有变量的默认类型是字符串型,那么只要我们把变量声明为整数型就可以进行运算了,
    # 定义变量b并赋值为3,具有整型属性。 declare -i x=3
    

    数组赋值

    #单个元素赋值 数组名[索引]=值
    #例如:weekdays[0]="Sunday"
    
    #一次全部赋值:数组名=(v1,v2...vn)
    #范例:title=("ceo" "coo" "cto")  #使用空格作为分隔符,而不是逗号
    

    使用数组

    ${数组名[索引]}
    
    #引用数组所有元素
    ${ARRAY_NAME[*]}${ARRAY_NAME[@]}
    
    

    删除数组

    #删除数组中的某一个元素
    unset 数组名[索引]
    
    #删除整个数组
    unset 数组名
    

    关联数组

    下标不是默认的数字0..n,而是自定义的。

    格式
    数组名[自定义的下标]=值
    #例如: aa[name1]=bob  --- echo ${aa[name1]}--->bob
    

    范例

    #随机生成十个数字,找出最大的和最小的
    #!/bin/bash
    max=0
    min=0
    declare -a arr #定义一个数组用于存储生成的是个随机数
    i=0
    while [ $i -le 10 ];do
    	arr[$i]=$RANDOM #给数组赋值
    	if [ $i -eq 0 ];then #把第一个数作为基准来判断后续数的大小
    		max=${arr[$i]}
    		min=${arr[$i]}
            else
    		if [ ${arr[$i]} -gt $max ];then 
    			max=${arr[$i]}
    		fi
    		if [ ${arr[$i]} -lt $min ];then 
    			min=${arr[$i]}
    		fi
    	fi
      let i++ #let工具需要一个变量来接受变量的值
    done
    echo "max is : $max , min is $min"
    

    shell的字符串处理

    shell字符串切片

    取出某个字符串中的部分内容。

    #数组中显示数组元素的个数:
    ${#数组名}
    #获取字符串的长度
    ${#var}
    例如:str=jkfjafasfa --->10
    
    #跳过字符串左边的几个
    ${var:num} #num:表示需要跳过几个
    #跳过字符串左边的几个,保留多少个
    ${var:offset:number} #number表示要保留的长度
    
    

    根据模式取字符串

    #删左留右边
    ${var#*word} #从左边开始找,一直找到word后,就把他们都删除掉(懒惰模式)
    ${var##*word} #从左边开始找,一直找到最右边的word后,就把他们都删除掉(贪婪模式)
    #范例:
    file="var/log/messages" ---echo ${file#*/}-->log/messages
    
    

    字符串的查找和替换

    #替换第一次匹配到的
    ${var/pattern/substr}
    
    #替换所有匹配到的
    ${var//pattern/substr}
    

    删除指定的字符串

    #删除掉第一次找到的
    ${var/pattern}
    
    #删除所有找的的
    ${var/pattern}
    
  • 相关阅读:
    OA系统开发
    5分钟入门卷积算法
    MISRA 2012学习笔记(5)-Rules 8.10
    Linux内存管理 (2):memblock 子系统的建立
    JDK8到JDK17有哪些吸引人的新特性?
    nginx转发https到tomcat报错403
    计算机算法分析与设计(15)---贪心算法(虚拟汽车加油问题和最优分解问题)
    MyBatis框架-缓存
    Android—AMS启动
    一日一技:用Python绘画有多好玩
  • 原文地址:https://www.cnblogs.com/heyongshen/p/16472084.html