数组与文本处理


Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0时表示成功,否则(非0值)表示失败或异常。
测试工具——test命令
test 
操作符         作用   
-d               测试文件是否为目录文件(Directory)
-f                测试文件是否为普通文件(File)
-e               测试目录或文件是否存在(Exist)。建议使用-e,-a可能不准确。
-a              测试目录或文件是否存在(Exist)
-r              测试当前用户是否有权限读取(Read)
-w             测试当前用户是否有权限写入(Write)
-x              测试当前用户是否有权限执行(eXcute)
-L              测试是否为符号链接(软链接文件)
-nt            判断文件A是否比文件B新-ot判断文件A是否比文件B旧
-ef            判断两个文件是否为同一文件。可用于硬链接,主要判断两个文件是否指向同一个inode。
-s FILE      判断文件是否存在且非空
-t fd    fd 指定文件描述符是否在某终端已经打开
-N FILE    文件自从上一次被读取之后是否被修改过
-O FILE    当前有效用户是否为文件属主
-G FILE    当前有效用户是否为文件属组

操作符    含义
-eq    等于(Equal)
-ne    不等于(Not Equal)
-gt    大于(Greater Than)
-lt    小于(Lesser Than)
-le    小于或等于(Lesser or Equal)
-ge    大于或等于(Greater or Equal)

逻辑测试(短路运算)
-a或&& :逻辑与,“而且”的意思,全真才为真。
-o或|| :逻辑或,“或者”的意思,一真即为真。
! :逻辑否。

使用三元运算符
使用 if语句双分支结构

ping命令:
-c,发送包的个数。
-i,发送的间隔时间。
-w(小写),多少秒后停止ping操作。
-W(大写),以毫秒为单位设置ping的超时时间 。

1.
if  判断条件
 ​
 then  条件成立的分支代码
 ​
 fi

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

3.
 case 变量引用 in
 模式1)
     命令分支1
     ;;
 模式2)
     命令分支2
     ;;
 ...
 *)
     默认命令分支
 esac

测试文件是否存在时,建议使用-e。如:[ -e /etc/passwd ]

七个小实验
检查用户家目录中的 test.sh 文件是否存在,并且检查是否有执行权限。

vim cunzai.sh
 #!/bin/bash
 #author:yu
 #date:2022/04/08
 ​
 [ -e ~/test.sh ]
 ​
 if [ $? -eq 0 ];then
    echo "test.sh存在"
    [ -x ~/test.sh ]
    if [ $? -eq 0 ];then
        echo "有执行权限"
    else
        echo "没有执行权限"
     fi
 else
    echo "test.sh不存在"
 fi

提示用户输入100米赛跑的秒数,要求判断秒数大于0且小于等于10秒的进入决赛,大于10秒的都淘汰,如果输入其它字符则提示重新输入;进入决赛的成员再进一步判断男女性别,男生进男生组,女生进女生组,如果输入错误请提示错误。
vim paobu.sh
 read -p "请输入您的100米赛跑秒数:" time
 ​
 if [ $time -gt 0 ] && [ $time -le 10 ]
 then
     echo "恭喜您进入决赛"
     read -p "请输入您的性别(男、女):" gender
     if [ $gender = "男" ]
     then
         echo "您进入男生组"
     elif [ $gender = "女" ]
     then
         echo "您进入女生组"
     else
         echo "输入有误,请重新输入"
     fi
 elif [ $time -gt 10 ]
 then
     echo "很遗憾,您无缘决赛"
 else
     echo "输入有误,请重新输入"
     bash $0
 fi


用case语句解压根据后缀名为 .tar.gz 或 .tar.bz2 的压缩包到 /opt 目录。

case $1 in
 *.tar.gz)
   echo "解压gz格式的压缩包"
   tar -zxvf $1 -C /opt/
   ;;
 *.tar.bz2)
   echo "解压bz2格式的压缩包"
   tar -jxvf $1 -C /opt/
   ;;
 *)
   echo "文件格式有误,无法解压"
 esac

提示用户输入内容,使用if 语句判断输入的内容是否为整数
vim zhengshu.sh
 #!/bin/bash
 #判断用户输入的数是否为整数
 
 read -p "请输入一个数字:" a
 let i=$a+1 &> /dev/null
 ​
 if [ $? -eq 0 ]
 then
      echo "${a}是整数"
 else
      echo "${a}不是整数"
 fi


根据上一题,在整数的情况下再判断输入的内容是奇数还是偶数。
vim jishu.sh
 #!/bin/bash
 #判断用户输入的数是否为整数
 #如果是整数,则继续判断是奇数还是偶数。
 ​
 read -p "请输入一个数字:" a
 let i=$a+1 &> /dev/null
 if [ $? -eq 0 ]
 then
      echo "$a是整数"
      b=$[${a}%2]
      case $b in
      0)
         echo "$a是偶数"
         ;;
      *)
         echo "$a是奇数"
      esac
 else
      echo "$a不是整数"
 fi

用case语句在/etc/init.d/目录中写一个firewalld脚本,并加入到系统服务管理中(#chkconfig: 2345 99 20),使能够使用 service firewalld start|stop|restart|status 来管理firewalld服务;如果命令选项不对,则提示 “用法: $0 {start|stop|status|restart}”
cd /etc/init.d
vim firewalld
#!/bin/bash
 #chkconfig: 2345 99 20   //必须加这一行,该脚本才能被chkconfig管理
 ​
 case $1 in
 start)
    echo "正在启动firewalld"
    systemctl start firewalld
    ;;
 stop)
    echo "正在关闭firewalld"
    systemctl stop firewalld
    ;;
 status)
    echo "查看firewalld的状态"
    systemctl status firewalld
    ;;
 restart)
    echo "正在重启firewalld"
    systemctl restart firewalld
    ;;
 *)
    echo "用法: $0 {start|stop|status|restart}"
 esac


chmod +x firewalld           //为脚本增加执行权限
chkconfig --add firewalld    //把该脚本加入系统服务管理中
chkconfig --list firewalld

service firewalld start
service firewalld stop
service firewalld status

循环:遍历、迭代、递归 。
遍历(traversal) - 按规则访问非线性结构中的每一项。
迭代(iterate) - 按顺序访问线性结构中的每一项。
递归(recursion) - 在函数内调用自身, 将复杂情况逐步转化成基本情况
常见的循环命令:for, while, until。

for循环语句   遍历
 1.依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束。
 2.如果省略 [in WORDS ... ] ,此时使用位置参数变量 in "$@"

for 变量名 in 取值列表
 do
    命令序列
 done

for遍历三种方式:
for i in {1..10}
for i in $(seq 1 10)
for ((i=1;i<=10;i++))

遍历奇数的三种方式
for i in {1..10..2}
for i in $(seq 1 2 10)
for ((i=1;i<=10;i+=2))

遍历偶数:
for i in {2..10..2}
for i in $(seq 2 2 10)
for ((i=2;i<=10;i+=2))

示例1  批量添加用户
用户名存放在users.txt文件中,每行一个
初始密码均设为123456
vim users.txt
liyi
 lisan
 liwu
 liliu
vim for2.sh 
for user in $(cat /root/users.txt)
 do
    useradd $user
    echo "123456" | passwd --stdin $user
 done
bash for2.sh 

实列2:根据IP地址检查主机状态
IP地址存放在ips.txt文件中,每行一个
使用ping命令检测各主机的连通性
vim ips.txt
192.168.92.10
 192.168.92.22
 192.168.92.1
vim for3.sh
for host in $(cat /data/ips.txt)
 do
    ping -c 3 -i 0.5 -w 4 $host &> /dev/null
    if [ $? -eq 0 ]
    then
        echo "$host is up"
    else
        echo "$host is down"
    fi
 done

实列三:生成8位随机密码(使用字符串分片的方法)
生成8位随机密码,密码范围为26个大小写英文字母和10个阿拉伯数字。
先定义密码取值范围:26个大小写英文字母和10个阿拉伯数字
每次取1个字符。
循环取8次
vim passran.sh
string="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
for i in {1..8}
do
 #每次循环随机获取0到字符串长度减1的下标值
    num=$[RANDOM % ${#string}]
    #进行字符串截取,每次随机取出1个字符
    var=${string:$num:1}
    #每次追加生成的密码,passwd+=$var等同于passwd=$passwd$var
    passwd+=$var
 done
 echo "本次生成的密码为:$passwd"

多线程执行脚本(并行执行)

普通for循环是串行,一个一个执行。
在do和done中间增加 { } 符号,可以多线程同时执行。

ping 192.168.72.0/24网段内的所有主机。


vim for4.sh
 #!/bin/bash
 #多线程,同时ping多台主机
 ​
 for ip in 192.168.72.{1..254}
 do
   {
   ping -c3 -w2 $ip &>/dev/null
   if [ $? -eq 0 ]
   then
       echo "$ip is up" >> /opt/up.txt
   else
       echo "$ip is down" >> /opt/down.txt
   fi
   }&
 #{ }表示多线程同时执行
 #增加 & 符号,表示将进程放到后台运行,后台命令之间是不区分先来后到关系的
done
wait

分隔符的作用演示:
使用for读取文件内容,文件中有空格


for的三个默认分隔符
空格、制表符 \t、换行符 \n。

使用for读取文件内容,文件中有空格
vim fen1.sh     //写脚本
 #!/bin/bash
 ​
 #从文件中获取变量值,$()表示调用命令执行的结果
 for name in $(cat name.txt)
 do
    echo "$name"
 done

cat name.txt    //查看文件内容,只有3行
bash fen1.sh    //运行脚本,显示5行内容

变量IFS定义的分隔符中有空格,for从文件中获取变量值时,以空格作为了分隔符,将"zhang san"分隔成了两行,"wang wu"也是如此。

在脚本中,先临时将变量IFS的值中的空格删除,使for语句不以空格作为分隔符,最后还原变量值。
vim fen2.sh       //写脚本
 #!/bin/bash
 ​
 #借用一个临时变量先保存IFS的原始值
 IFS_OLD=$IFS
 #删除空格和制表符,只保留换行符作为分隔符
 IFS=$'\n'
 ​
 #从文件中获取变量值,$()表示调用命令执行的结果
 for name in $(cat name.txt)
 do
    echo "$name"
 done
 ​
 #还原变量IFS的原始值
 IFS=$IFS_OLD


 while循环应用示例
批量添加用户
用户名称以stu开头,按数字顺序进行编号
一共添加20个用户,即stu1、stu2、...... 、stu20
初始密码均设为123456

vim while01.sh    //创建脚本
 #!/bin/bash
 #用户名称以stu开头,按数字顺序进行编号
 #一共添加20个用户,即stu1、stu2、...... 、stu20
 #初始密码均设为123456
 ​
 a=1
 while [ $a -le 20 ]
 do
    useradd stu$a -M
    echo "123456"| passwd --stdin stu$a &>/dev/dull
    let a++
    #一定要有变量迭代的过程
 done


猜商品价格游戏

vim while02.sh         //创建脚本
 #!/bin/bash
 # 猜商品价格游戏
 # 通过变量RANDOM获得随机数
 # 提示用户猜测并记录次数,猜中后退出循环
 #-----------------------------------------
 #商品价格
 price=$[RANDOM%100+1]
 #猜的次数
 a=0
 ​
 #死循环,一直为真。需要人为设置退出。
 while true
 do
    read -p "请猜测商品价格(1-100):" num
    let a++
    if [ $num -eq $price ]
    then
         echo "恭喜你猜对了"
         echo "你一共猜了 $a 次"
         exit
         #猜对价格后,退出脚本进程
     elif [ $num -lt $price ]
     then
          echo "太低了"
     else [ $num -gt $price ]
           echo "太高了"
      fi
 done


while和read结合 读取文件内容

read 每次只能读取一行内容,如果read识别到了换行符,就结束这一次的读取。
linux中的换行符是:换行+回车( 即“\n” )

把test文件重定向输入给while,之后read逐行读取
while read line
 do
    echo $line
 done < test.txt

把文件内容通过管道符传给while,之后read逐行读取
 #!/bin/bash
 #把文件内容通过管道符传给while,之后read逐行读取
 ​
 cat test.txt | while read line
 do
      echo $line
 done 

until循环语句
重复测试某个条件,只要条件不成立则反复执行。
格式:
 vim until01.sh        //写脚本
 #!/bin/bash
 # 计算1到10的和
 ​
 sum=0
 i=1
 # 条件不成立才执行命令序列
 until [ $i -gt 10 ]
 do
    let sum=$[sum+i]
    let i++
 done
 echo "1到10的求和结果是:$sum"
 ​
为指定用户发送在线消息

为指定用户发送在线消息;
若用户不在线(未登录系统),则每10分钟试一次,直至用户登录系统后再发送消息;
用户名与消息通过位置参数传递给脚本。
vim until02.sh
 #!/bin/bash
 #为指定用户发送在线消息
 #若用户不在线(未登录系统),则每10分钟试一次,直至用户
 登录系统后再发送消息
 #用户名与消息通过位置参数传递给脚本
 ​
 # 只要用户在线不成立(即用户不在线).就执行命令序列
 until who |grep "$1" &> /dev/null
 do
    echo "$1 不在线"
    sleep 600
 done
 echo $2 | write $1

你可能感兴趣的:(linux,运维)