bashshell if read for while until 的使用

来源:互联网 发布:商场女装品牌推荐 知乎 编辑:程序博客网 时间:2024/04/19 17:18

8月14日上课内容

(一)课前回顾

前言:/etc/passwd文件保存了每一个系统用户和登入用户的基本信息,你是否真正了解它每一个字段的意义呢?

  • 详细讲解/etc/passwd文件内容
查看/etc/passwd文件的内容[root@7 ~]# cat /etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2:daemon:/sbin:/sbin/nologinadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologingames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTP User:/var/ftp:/sbin/nologinnobody:x:99:99:Nobody:/:/sbin/nologinavahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologinsystemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologinsystemd-network:x:998:996:systemd Network Management:/:/sbin/nologindbus:x:81:81:System message bus:/:/sbin/nologinpolkitd:x:997:995:User for polkitd:/:/sbin/nologinabrt:x:173:173::/etc/abrt:/sbin/nologin
第一字段:用户名(也被称为登录名);在上面的例子中,我们看到系统中所有的用户第二字段:密码;在/etc/passwd中我们看到的是一个x,其实密码已被映射到/etc/shadow文件中第三字段:UID 第四字段:GID第五字段:用户名全称,这是可选的,可以不设置,这里其实就是在useradd命令创建用户的时候使用-c选项指定的用户的信息第六字段:用户的家目录所在位置第七字段:用户所用SHELL的类型,用户的shell有多种,可以是/bin/bash表示可以登入的用户;也可以是/sbin/nologin,一般用户设置系统用户或非登入用户

(二)bash编程权威指南3

前言:在任何编程语言中,为了控制代码的执行的顺序,都会有一些控制流语法,这些控制流语法就是我们通常所说的if else判断流,while、for in循环控制流等。那么今天我们就来看看这些控制流是如何来控制脚本中的代码的执行顺序的

  • (一)选择执行语句
  • 单分支的if语句
if 测试条件;then    如果满足条件就执行这里的代码fi
  • 双分支的if语句
if 测试条件;then    如果满足条件就执行这里的代码else    如果不满足条件就执行这里的代码fi
  • 练习1:通过参数传递一个用户名给脚本,此用户不存在,则添加,密码与用户名相同
#!/bin/bash# description# 如果没有传递参数,直接退出if [ $# -lt 1 ];then    echo "please send argument"    exit 1fiif grep "^$1\>" /etc/passwd &>/dev/null;then    echo "user $1 exists"else        useradd $1    echo $1 | passwd --stdin $1 &>/dev/null    echo " add user $1 "fi
  • 练习2:通过参数传递一个用户名给脚本,此用户存在,则删除用户以及其家目录和邮件目录
#!/bin/bash# descriptionif  [ $# -lt 1 ];then    echo "please send a argument."    exit 1fiif id -u $1 &> /dev/null;then    userdel -r $1    echo "delete user $1"else    echo "user $1 doesn't exists"    fi
  • 练习3:通过命令行参数给定两个数字,输出其中最大的数值
#!/bin/bash# 通过命令行参数给定两个数字,输出其中最大的数值if [ $# -lt 2 ];then    echo " Please input two arguments."    exit 1fiif [ $1 -eq $2 ];then    echo "$1 equals to $2"    exit 1fiif [ $1 -gt $2 ];then    echo " The big one is $1 "else    echo " The big one is $2 "fi
#!/bin/bash# 通过命令行参数给定两个数字,输出其中最大的数值if [ $# -lt 2 ];then    echo " Please input two arguments."    exit 1fideclare -i max=$1if [ $max -lt $2 ];then    max=$2fiecho " The big one is $max "
  • 练习4:通过命令行参数给定一个用户名,判断其ID号是偶数还是奇数
#!/bin/bash# 通过命令行参数给定一个用户名,判断其ID号是偶数还是奇数if [ $# -lt 1 ];then    echo "Please input a argument."    exit 1fiif id -u $1 &> /dev/null;then    idNum=$(id -u $1)    let s=$idNum%2    # 判断余数是0还是1,如果是0,那么就是偶数,如果是1,就是奇数    if [ $s -eq 0 ];then        echo "$1'ID number is $idNum and oven"    else        echo "$1'ID number is $idNum and odd"    fielse    echo "user $1 doesn't exits" fi
  • 练习5:通过命令行参数给定两个两个文件名,如果某文件不存在,则结束脚本执行,如果都存在时返回两个文件的行数之和
#!/bin/bash# 通过命令行参数给定两个两个文件名,如果某文件不存在,则结束脚本执行,如果都存在时返回两个文件的行数之和if [ $# -lt 2 ];then    echo " Please input two arguments. "    exit 1fiif [ -e $1 -a -e $2 ];then    totalLines=$[ $(grep ".*" $1|wc -l)+$(grep ".*" $2|wc -l) ]    echo " The total lines are $totalLines "else    echo " the file doesn't exists !"    exit 1fi
  • (二)read命令:通过键盘输入数据,将键盘输入的值传递给脚本的中定义的变量,从而完成变量赋值操作 。脚本中使用read命令可以使得用户能够与程序进行交互
  • read命令的使用格式
# 这里变量名的意义在于将用户输入的值传递给这个变量名,那么在脚本中我们就可以拿到用户输入的值了read [选项] [变量名] 选项:    -p (promp):在用户在键盘输入数据时,指定显示提示符    -t(timeout):指定超时时间,如果用户在指定的超时时间都没有输入的话,那么就终止脚本的执行
  • 示例:通过脚本创建一个用户,并设置密码,要求:需要用户交互式输入用户名和密码,如果用户名存在,终止脚本,如果不存在就创建,且设置密码
#!/bin/bash#通过脚本创建一个用户,并设置密码,要求:需要用户交互式输入用户名和密码提示用户输入用户名read -p "Enter a user name:" name[ -z "$name" ] && echo "a user name is needed." && exit 1# 如果用户输入用户名和密码完成,创建用户和密码if id $name &>/dev/null;then    echo "$name already exists."    exit 2else# 如果用户输入用户名,提示用户输入密码    read -p "Enter a password for $name, default is 'password':" password    [ -z "$password" ] && password="password"    adduser $name    echo "$password" | password --stdin $name &>/dev/null    echo "Add user $name."fi

(三)bash编程权威指南4(if嵌套和多分支)


  • (1)在运行脚本前,我们一般先对脚本的语法进行检查,如果脚本有bug,我们再调试脚本
  • 语法检查
bash -n 脚本路径
  • 脚本调试
bash -x 脚本路径
  • (2)过程式编程语言的执行流程
顺序执行选择执行循环执行
  • 选择执行
(1)&&,||      command1 && command2:如果command1正确,也执行command2;如果command1不正确,不执行command2    command1 || command2:如果command1正确,不执行command2;如果command1不正确,执行command2(2)if语句    if语句:三种格式     我们之前已经学习了单分支的if语句    接下来学习if多分支和if嵌套语句(3)case语句 
  • if嵌套语句格式
if [ 条件 ];then    if [ 条件 ];then        执行这里的代码    fifi
if [ 条件 ];then    if [ 条件 ];then        执行这里的代码    fielse    if [ 条件 ];then        执行这里的代码    fifi
  • if 多分支语句格式(注意:多个分支只会执行一个,执行首先为真的分支)
if  [ 条件1 ];then        条件1为真执行这里的代码elif [ 条件2 ];then        条件2为真执行这里的代码elif [ 条件3 ];then        条件3为真执行这里的代码...elif [ 条件n ];then        条件n为真执行这里的代码else        如果所有的条件都不满足时,执行这里的代码fi注意:多个分支只会执行一个,执行首先为真的分支
  • 示例代码演示:通过脚本参数传递一个文件路径给脚本,判断此文件的类型
#!/bin/bash#通过给定的文件路径,判断文件是什么类型的文件if [ $# -lt 1 ];then    echo "A argument is needed."    exit 1fiif ! [ -e $1 ];then    echo "No such file or directory."    exit 2fiif [ -f $1 ];then    echo "Common file"elif [ -d $1 ];then    echo "Directory"elif [ -L $1 ];then    echo "Symbolic link"elif [ -b $1 ];then    echo "block special file"elif [  -c $1 ];then    echo "character special file"elif [  -S $1 ];then    echo "Socket file"else    echo "Unknow"fi# 注意:if语句可以嵌套
  • 练习又来了
  • 写一个脚本
    (1)传递一个参数给脚本,此参数为用户名
    (2)根据其ID号来判断用户类型:0:管理员 ,1-499:系统用户,500+:为登入用户, 输出用户是那种类型的用户
#!/bin/bash#(1)传递一个参数给脚本,此参数为用户名# (2)根据其ID号来判断用户类型:0:管理员 ,1-999:系统用户,1000+:为登入用户if [ $# -lt 1 ]; then    echo "A argument is needed."    exit 1fi# 如何输入的用户名存在# 注意通过命令来判断成功与否不能加[]if id -u $1 &>/dev/null;then    userid=$(id -u $1)    if [ $userid -eq 0 ];then        echo "Administrator"    elif [ $userid -gt 1 -a $userid -lt 499 ];then        echo " System user"    elif [ $userid -ge 500 ];then        echo "Login user"    fielse    echo "NO such user."    fi
  • 写一个脚本
    (1)列出如下菜单给用户
    disk) show disks info
    mem)show memory info
    cpu)show cpu info
    *)quit
    (2)提示用户给出自己的选择,而后显示对应其选择的相应系统信息
#!/bin/bashcat << EOFdisk) show disks infomem)show memory infocpu)show cpu info*)quitEOFread -p "Please input your option:" option# 如果用户输入的是大写,直接将大写转变为小写option=$(echo $option | tr [A-Z] [a-z])if [ $option == "disk" ]; then    fdisk -lelif [ $option == "mem" ]; then    free -melif [ $option == "cpu" ]; then    lscpuelif [ $option == "*" ]; then    exit 1else    echo "Wrong option"fi

(四)bash编程权威指南5(循环)

前言:循环就是将一段代码重复执行0,1次或多次。
进入条件:条件满足时,需要进入循环
退出条件:每个循环都应该有退出条件,有机会退出循环
bash的循环分类:
  • for循环
  • while循环
  • until循环

  • (1)for循环有两种格式 (重点必须掌握)
    • 第一种格式:遍历列表 (重点必须掌握)
    • 第二种格式:控制变量 (重点必须掌握)
  • 变量列表
for 变量 in 列表; do    循环体done进入条件:只要列表中有元素,即可进入循环退出循环:列表中的元素遍历完成
  • 示例
#!/bin/bashfor username in user1 user2 user3;do    if id $username &>/dev/null;then        echo "$username is already exists."    else            useradd $username        echo "Add &username success"done
  • 列表生成的方式
1)直接取出     例如: user1 user2 user3(2)整数列表     例如 {1..100}    例如  `seq 1 2 100`  注意:中间的2表示步长(3)返回列表的命令    `ls /var/log/`(4)glob    例如: /var/log/*(5)变量引用,如:@* ,
  • 示例1:求100内所有正整数之和
#!/bin/bash# 求100内所有正整数之和# 申明sum为正整数declare -i sum=0for i in {1..100}; do    sum=$[ $sum+$i ]doneecho "$sum"  
  • 示例2:列出/var/log/目录下所有文件的类型
#!/bin/bash# 列出/var/log/目录下所有文件的类型for option in /var/log/*; do    if [ -f $option ];then        echo "$option is Common file"    elif [ -d $option ];then        echo "$option is Directory"    elif [ -L $option ];then        echo "$option is Symbolic link"    elif [ -b $option ];then        echo "$option is block special file"    elif [  -c $option ];then        echo "$option is character special file"    elif [  -S $option ];then        echo "$option is Socket file"    else        echo "Unknow"    fidone
  • 练习1:分别求100以内所有偶数之和,奇数之和
#!/bin/bash# 1:分别求100以内所有偶数之和,奇数之和declare -i oven=0declare -i odd=0for i in {1..100}; do    count=$[ $i % 2 ]    if [[ $count == 0 ]]; then        oven=$[ $oven + $i ]    else        odd=$[ $odd + $i ]    fidoneecho "oven is $oven"echo "odd is $odd"     
  • 练习2:计算当前用户的id之和
#!/bin/bash# 2:计算当前用户的id之和 declare -i idcount=0# 取出/etc/passwd文件中用户的个数userRow=$(wc -l /etc/passwd|cut -d" " -f1)# 这里不能使用{},作为列表,用seq:for i in `seq 1 $userRow`; dofor i in $(seq 1 $userRow); do    userName=$(cut -d: -f1 /etc/passwd|sed -n "$i"p)    idcount=$[ $idcount + $(id -u $userName) ]doneecho "$idcount"
  • 练习3:通过脚本参数传递一个目录,计算所有的文本文件的行数之和,并说明文件的总数
#/bin/bash#3:通过脚本参数传递一个目录,计算所有的文本文件的行数之和,并说明文件的总数if [[ $# < 1 ]];then    echo "A argument is needed."    exit 1fideclare -i fileCounts=0declare -i rowsCounts=0# 文件数fileCounts=$( find $1 -type f | wc -l )for i in `seq 1 $fileCounts`; do    #这里的egrep其实可以不要,也可以取出行数    rowCount=$(find $1 -type f -exec wc -l {} \; | cut -d" " -f1 | sed -n "$i"p)    rowsCounts=$[ $rowsCounts + $rowCount ]doneecho "fileCounts is $fileCounts , rowsCounts is $rowsCounts"
  • 控制变量
for((i=1;i<10;i++));do    进入循环代码done
  • (2)while循环 (重点必须掌握)
    • while CONDITION ; do
      循环体
      循环控制变量的修正表达式
      done
      进入条件:CONDITION测试为“真”
      退出条件:CONDITION测试为“假”
  • 示例:求100以内所有正整数之和
#!/bin/bash#求100以内所有正整数之和declare -i sum=0declare -i i=1while [ $i -le 100 ]; do    sum=$[ $sum+$i ]    let i++doneecho "sum is $sum"
  • (3)until循环 (非重点了解即可)
    • until CONDITION ; do
      循环体
      循环控制变量
      done
      进入条件:CONDITION测试为“假”
      退出条件:CONDITION测试为“真”
  • 示例:求100以内所有正整数之和
i=1sum=0until [ $i -gt 100 ];do    sum=$[ $sum+$i ]    let i++doneecho "sum to $sum"
  • 综合练习1:分别使用while for until实现,求100以内所有的偶数之和,100以内奇数之和
#!/bin/bash# 分别求100以内所有的偶数之和,100以内奇数之和declare -i oven=0declare -i odd=0for i in  {1..100}; do    count=$[ $i%2 ]    if [ $count -eq 0 ]; then        oven=$[ $oven+$i ]    else        odd=$[ $odd+$i ]    fidoneecho "odd is $odd"echo "oven is $oven"
oven=0odd=0i=1 while [ $i -le 100 ]; do    count=$[ $i%2 ]    if [ $count -eq 0 ]; then        let oven+=$i    else        let odd+=$i    fi    let i++ doneecho "odd is $odd"echo "oven is $oven"
oven=0odd=0i=1until [ $i -gt 100 ]; do    count=$[ $i%2 ]    if [ $count -eq 0 ]; then        let oven+=$i    else        let odd+=$i    fi    let i++doneecho "odd is $odd"echo "oven is $oven"
  • 综合练习2:创建9个用户,user101-user109;密码同用户名, 如果这些用户存在就删除,不存在就创建
#!/bin/bashfor i in `seq 1 10`;do        if id user10"$i" &> /dev/null;then                userdel -r user10"$i"        else                useradd user10"$i"                echo "user10$i" | passwd --stdin user10"$i" &> /dev/null                echo "create user user10$i"        fidone
  • 综合练习3:打印九九乘法表
#!/bin/bash# 注意:这里的echo 的 -n选项表示不换行for((i=1;i<9;i++));do    for((j=1;j<=$i;j++));do        echo -n "$j X $i = $[ $j*$i ]  "    done    echodone
  • 综合练习4:打印逆序的九九乘法表
#!/bin/bash#打印逆序九九乘法表declare -i k=9while [ $k -ge 1 ]; do        for i in `seq 1 $k| sort -n -r`;do            echo -n "$i X $k = $[ $i*$k ]  "        done        echo ""        let k--done

(五)bash编程权威指南5

前言:continue、break、sleep命令、死循环,在循环语句中扮演了重要的角色,他们可以控制整个循环的执行过程
continue:跳出本次循环,进入下一轮循环
break:跳出整个循环
sleep:程序睡眠一个时间段
死循环:条件为true,永远为死循环

  • continue语句格式
while  [ 条件1 ]; do    满足条件执行这里的代码    if [ 条件2 ]; then        # 跳出当前循环进入下一轮循环        continue    fi    满足条件执行这里的代码done
  • 示例:求100以内所有的偶数之和
#/bin/bash# 求100以内所有的偶数之和# authordeclare -i evensum=0for i in {1..100}; do    if [ $[ $i%2 ] -eq 1 ];then        continue    fi    let evensum+=$idoneecho "evensum is $evensum"
#/bin/bash# 求100以内所有的偶数之和# authordeclare -i evensum=0declare -i i=0while [ $i -lt 100 ]; do        let i++    if [ $[ $i%2 ] -eq 1 ];then        continue    fi    let evensum+=$idoneecho "evensum is $evensum"
  • break :直接跳出整个循环
while [条件1]; do    执行这里的代码    if [条件2]; then        break    fi    执行这里的代码done
  • 死循环:如何创建死循环
while true;do    循环体done退出方式:某个测试条件满足的时候,让循环体执行break命令就是
  • 示例:计算100以内奇数之和
#/bin/bash# description# authordeclare -i oddsum=0declare -i i=1while true; do    let oddsum=$oddsum+$i    let i=$i+2    if [ $i -gt 100 ];then        break    fidoneecho "oddsum is $oddsum"
  • sleep命令
  • 示例:每隔3秒钟到系统上获取已经登入的用户的信息,其中,如果sb用户登入了系统,则给QQ发送邮件,主题为“sb user is login”,并退出
先修改/etc/mail.rc文件set from=yinhuanyi_cn@163.com smtp=smtp.163.comset smtp-auth-user=yinhuanyi_cn@163.com smtp-auth-password=yhy3426356set smtp-auth=login
while true; do    sleep 3    if who | grep logstash &>/dev/null;then        echo "sb user is login" | mail -s 'somebody login' 307443272@qq.com        break    fidone
  • while循环的特殊用法(遍历文件的行)
while read VARIABLE;do    循环体done < /PATH/TO/FILE意思是:依次读取/PATH/TO/FILE文件中的每一行,且将其赋值给VARIABLE变量
  • 示例:找出ID号为偶数的用户,显示其用户名、ID、及默认的shell
#/bin/bash# 找出ID号为偶数的用户,显示其用户名、ID、及默认的shell# authorwhile read line; do        ID=$(echo $line|cut -d: -f3)        if [ $[ $ID%2 ] -eq 0 ];then                username=$(echo $line | cut -d: -f1)                shell=$(echo $line | cut -d: -f7)        echo "username is $username, ID is $ID , shell is $shell"        fidone < /etc/passwd
  • 实战示例:一直监听/data/目录下的文件变化,一旦变化就会把变化的信息赋值给file变量,那么对于file来说,while语句的循环体内并不需要拿到file的值,这里的while语句的功用在于只要file被赋值了,就会执行循环体内的代码。while内部的代码是无差异的数据同步。
#!/bin/bashinotify=/usr/bin/inotifywaitwhile read file; do        /usr/bin/rsync -avz --delete /data/ nfs@192.168.23.26::data --password-file=/etc/rsync.passworddone < $inotify -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f' -e modify,delete,create,attrib,close_write /data
  • for循环的特殊用法
for((控制变量初始化;条件判断表达式;控制变量修正语句));do    循环体done注意:控制变量初始化:仅仅在循环代码开始运行时执行一次控制变量的修正语句:每轮循环结束会先进行控制变量修正运算,而后再做条件判断示例:1到100的和declare -i sum=0for((i=1;i<=100;i++));do        let sum+=$idoneecho "sum is $sum"示例:打印九九乘法表#/bin/bash# description# authorfor((i=1;i<=9;i++));do        for((j=1;j<=i;j++));do                echo -ne "${j}X${i}=$[ ${j}*${i} ]\t"        done        echodone
阅读全文
1 0
原创粉丝点击