linux之基础shell脚本编程2 if语句循环判断

本章命令:if case while for unit break continue

linux之基础shell脚本编程1  基础变量赋值

linux之基础shell脚本编程3 函数数组

linux之基础shell脚本编程4 字符串操作,变量赋值,配置用户环境 


4.4.4 组合测试

第一种方式

 COMMAND1 && COMMAND2 并且

 COMMADN1 || COMMAND2 或者

 !COMMAND 非

第二种方式

 EXPRESSION1 -a EXPRESSION2 并且

 EXPRESSION1 -o EXPRESSION2 或者

 !EXPRESSION 非

 必须使用测试命令进行

[ -z "$HOSTNAME" -o $HOSTNAME == "localhost.localdomain" ] && hostname www.liuyuworld.com
### 判断hostname是否为空或者hostname是"localhost.localdomain" 如果前面有一个条件成立,然后执行hostname 命令
[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab ##判断文件是否存在并且可执行


实战训练4

1、chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判断当前用户对/tmp/fiile1文件 是否不可读且不可写 

#!/bin/bash
[ ! -r /tmp/file1 ] && [ ! -w /tmp/file1 ] && echo "不可读写" || echo "可读写"
[root@centos7 shell]# chmod -rw /tmp/file1 
[root@centos7 shell]# ll /tmp/file1 
----------. 1 root root 0 Aug 10 16:22 /tmp/file1
[root@centos7 shell]# bash per.sh 
可读写
[root@centos7 shell]# su cent
[cent@centos7 shell]$ bash per.sh 
不可读写

2、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和充许普通用户登录系统

思路:当/etc/目录下存在 nologin 文件时,普通用户会无法登陆,因此,我们只需要通过删除或增加该文件来限制普通用户是否可登陆

[root@centos7 shell]# cat login.sh nologin.sh 
#!/bin/bash
[ -e /etc/nologin ] && echo "rm -f /etc/nologin enable user login "
#!/bin/bash
[ -a /etc/nologin ]  ||  touch /etc/nologin
echo "disable user login "

执行 bash nologin.sh 脚本时,登陆普通用户会提示

Connecting to 172.18.16.152:22...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
Connection closed by foreign host.
Disconnected from remote host(centos7) at 20:11:18.

然后执行bash login.sh 脚本时,就可以直接登陆了

Connecting to 172.18.16.152:22...
Connection established.
To escape to local shell, press 'Ctrl+Alt+]'.
Last failed login: Fri Aug 12 20:11:09 CST 2016 from 172.18.16.171 on ssh:notty
There was 1 failed login attempt since the last successful login.
Last login: Fri Aug 12 20:10:29 2016 from 172.18.16.171

 seq -f'%02g' 1 20  生成01-20


五,流程控制

5.1 使用read命令来接受输入

使用read来把输入值分配给一个或多个shell变量:

 -p :指定要显示的提示

 -t :TIMEOUT

比如:

read -p "print a filename:" file

注意:read 从标准输入中读取值,给每一个单词分配一个变量,所有剩余单词都被分配给最后一个变量

5.2 条件选择if语句

if语句是选择执行,并且可以嵌套执行

单分支:

 if 判断条件 ; then

    条件为真的分支代码

 fi

if [ $1 -gt 60 ];then
    echo "the grade is pass"
fi

双分支:

 if 判断条件 ; then

    条件为真的分支代码

 else

    条件为假的分支代码

 fi

if [ $1 -gt 60 ];then
    echo "the grade is pass"
else
    echo "the grade is not pass"
fi

多分支:

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

if CONDITION1; then 
    if-true 
elif CONDITION2; then 
    if-ture 
elif CONDITION3; then 
    if-ture 
    ... 
else 
    all-false 
fi

 

5.3 条件判断case语句

case 变量引用 in 

PAT1) 

分支1 

;; 

PAT2) 

分支2 

;; 

… 

*) 

默认分支 

;; 

esac

case支持glob风格的通配符: 

 *: 任意长度任意字符 

 ?: 任意单个字符 

 []:指定范围内的任意单个字符 

 a|b: a或b


实战训练5

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

##方法一
[root@centos7 test]# cat createuser.sh 
#!/bin/bash
id $1 &>/dev/null && (echo '该用户已存在,信息为:' ; id $1) || ( useradd $1 ; echo '添加成功,信息为:' ; id $1)
[root@centos7 test]# bash createuser.sh user01
添加成功,信息为:
uid=1005(user01) gid=1005(user01) groups=1005(user01)
[root@centos7 test]# bash createuser.sh user01
该用户已存在,信息为:
uid=1005(user01) gid=1005(user01) groups=1005(user01)
##方法二
#!/bin/bash
if  id $1 &> /dev/null  ; then
     echo "$1 is exsit,the info is id $1"
else
    useradd $1 && echo "useradd is successful ,the info is id $1"
fi

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

#!/bin/bash
read -p "please input 'yes' or 'no' : " string
case $string in
[Yy][Ee][sS]|Y|y)
    echo "you input is yes"
    ;;
[Nn][oO]|N|n)
    echo "you input is no"
    ;;
*)
    echo "you input is other info"
    ;;
esac

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

#!/bin/bash
read -p "please input a path of the file :" files
if [ -b $files ];then
        echo "该文件是块设备"
elif [ -c $files ] ;then
        echo "该文件是字符设备"
elif [ -f $files ];then
        echo "该文件是普通文件"
elif [ -h $files ];then
        echo "该文件是符号链接文件"
elif [ -p $files ];then
        echo "该文件是管道文件"
elif [ -S $files ];then
        echo "该文件是套接字文件"
elif [ -d $files ];then
        echo "该文件是目录文件"
else
    echo "文件或目录不存在"
fi

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

#!/bin/bash
read -p "please input :" arg
if  [[ $arg =~ ^[[:digit:]]+$  ]] && [ $(expr $arg + 0)  != 0  ]    ;then
    echo "是正整数"
else
    echo "不是正整数"
fi


六,循环

循环执行:

  将某代码重复运行多次

  重复运行多次

    循环次数事先已知

    循环次数事先未知

  有进入条件和退出条件

for,while,until

6.1  

for循环

for 变量名 in 列表;do

    循环体

done

执行机制:依次将列表中的元素赋值给"变量名";每次赋值后即执行一次循环体,直到类表中的元素耗尽,循环结束

列表生成方式: 

(1) 直接给出列表 

(2) 整数列表: 

    (a) {start..end} 

    (b) $(seq [start [step]] end) 

(3) 返回列表的命令 $(COMMAND) 

(4) 使用glob,如:*.sh 

(5) 变量引用: $@, $*


实战训练6

要求:用for实现

1、判断/var/目录下所有文件的类型 

#!/bin/bash
for i in /var/* ;do
if [ -b $i ];then
        echo "$i是块设备"
elif [ -c $i ] ;then
        echo "$i是字符设备"
elif [ -f $i ];then
        echo "$i是普通文件"
elif [ -h $i ];then
        echo "$i是符号链接文件"
elif [ -p $i ];then
        echo "$i是管道文件"
elif [ -S $i ];then
        echo "$i是套接字文件"
elif [ -d $i ];then
        echo "$i是目录文件"
else
         echo "文件或目录不存在"
fi
done

2、添加10个用户user1-user10,密码同用户名 

#!/bin/bash
#添加10个用户
for i in user{1..10} ;do
    id $i &> /dev/null && echo "$i 用户已存在"|| (adduser $i ;echo "$i 用户添加成功")
    echo $i:$i | chpasswd
done
#!/bin/bash
#删除10个用户
for i in user{1..10} ;do
    id $i &> /dev/null && (userdel -fr $i ;echo  "$i 删除成功") || echo "$i 删除失败,该用户肯不存在"
done

3、/etc/rc.d/rc3.d目录下分别有多个以K开头和以S开头的 文件;分别读取每个文件,以K开头的文件输出为文件加stop ,以S开头的文件输出为文件名加start; “K34filename stop” “S66filename start” 

#!/bin/bash
for i in /etc/rc.d/rc3.d/[SK]* ;do
if [ $(basename $i | cut -c1) == "K" ] ;then
    echo "basename $i stop"
else
    echo "basename $i start"
fi
done

4、写一个脚本,提示输入正整数n的值,计算1+2+3+…n的 总和 

#!/bin/bash
read -p "please input a number:" n
sum=0
for i in $(seq 1 $n);do
    let sum+=$i
done
echo "the sum is $sum"

5、写一个脚本,提示请输入网络地址,如192.168.0.0,判 断输入的网段中主机在线状态

 

#!/bin/bash
file=mktemp /tmp/pingip.XXXXXX
read -p "请输入网络地址 :" ip
i=echo $ip | cut -d'.' -f1-3
for z in {1..255};do
{
    ip=$i.$z
    ping -c1 -W1 $ip &> /dev/null && (echo "$ip is up" ) && echo ip >> $file
}&
done

sleep 1
echo "cat $file | wc -l在线"
rm -f $file &> /dev/null

6、打印九九乘法表

#!/bin/bash
for i in  {1..9};do
    for j in $(seq 1 $i) ;do
      echo -ne "${j}x${i}=$[i*j]\t"
    done
    echo 
done

6.2

while 循环

语法:

 while CONDITION; do 

    循环体 

 done 

CONDITION:循环控制条件;进入循环之前,先做一次判 断;每一次循环之后会再次做判断;条件为“true”,则执行 一次循环;直到条件测试状态为“false”终止循环 

因此:CONDTION一般应该有循环控制变量;而此变量的值会在循环体不断地被修正 

进入条件:CONDITION为true

退出条件:CONDITION为false


实战训练7

要求:用while实现

1、求100以内所有正整数之和 

#!/bin/bash
sum=0
i=0
while [ $i -le 100 ] ;do
    let sum+=$i
    let i++
    done
echo $sum

2、通过ping命令探测172.16.250.1-254范围内的所有主机的在线状态,统计在线主机和离线主机各多少。 

#!/bin/bash
ip=10.1.250.
i=1
sum=0
while [ $i -lt 255 ] ;do
    if ping -c1 -W1 $ip$i &> /dev/null ;then
        let sum+=1
        echo "$ip$i  is up"
    else
        echo "$ip$i  is down"
    fi
    let i+=1
done
echo "在线主机$sum台,离线$[255-sum]主机台"

3、打印九九乘法表

#!/bin/bash
i=1
j=1
while [ $i -le 9 ] ;do
    while [ $j -le $i  ] ;do
        echo -ne "${j}x${i}=$[i*j]\t"
        let j+=1
    done
    let i+=1
    j=1
    echo
done

blob.png

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

#!/bin/bash
let i=0,min=max=$RANDOM
echo "$min "
while [ $i -lt 9  ];do
    ran=$RANDOM
    echo "$ran "
    if [ $ran -ge $max ];then 
        let max=ran
    fi
    if [ $ran -le $min ];then
        let min=ran
    fi
    let i+=1
done
echo "最大值是 $max ,最小值是 $min"

5、打印国际象棋棋盘

#!/bin/bash
let x=y=1
h=8
while [ $x -le $h ];do
    while [ $y -le $h ];do
        if [ $[(x+y)%2] -eq 0 ]  ;then
            echo -en "\033[47m  \033[0m"
        else
            echo -en "\033[40m  \033[0m"
        fi
    let y+=1
    done
    echo
let x+=1,y=1
done

blob.png

#!/bin/bash
num=8
for((i=1;i<=$num;i++)){
for ((j=1;j<=$num;j++))
{
    if [ $[(i+j)%2] -eq 0 ];then
        echo -en "\033[47m  \033[0m"
    else
        echo -en "\033[42m  \033[0m"
    fi
}
echo
}


6.3

until循环 (和while循环执行条件相反)

  until CONDITION; do 

    循环体 

  done

进入条件: CONDITION 为false 

退出条件: CONDITION 为true

6.4

循环控制语句continue,break

用于循环体中

continue [N]:提前结束第N层的本轮循环,而直接进入下一 轮判断;最内层为第1层 

while CONDTIITON1; do 
   CMD1
   ... 
   if CONDITION2; then 
       continue 
   fi 
   CMDn 
    ... 
done

break [N]:提前结束第N层循环,最内层为第1层 

while CONDTIITON1; do 
    CMD1 
    ... 
    if CONDITION2; then 
       break 
    fi 
    CMDn
    ... 
done

比如无限循环:

while true; do 
    循环体 
done
until false; do 
   循环体 
Done


实战训练8

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

#!/bin/bash
username=cent
{
while true ;do
    if who | egrep "^\b$username\b" &> /dev/null ;then
        who | egrep "^\b$username\b" >> /var/log/login.log
        echo "$username 已经登录"
        echo "fuck ,go out my system" | write $username
    else
        echo "$username 已经下线"
    fi
    sleep 3
done
}
#!/bin/bash
username=hacker
exituser()
{
    echo "fuck you,you will exit,haha" | write $username
    sleep 2
    pidlist=$(ps -f h -u $username | tr -s ' '|cut -d' ' -f2)
    for i in $pidlist ;do
        kill -9 $i
#   echo "正在结束进程"
    done
}
while true ;do
    if w | egrep "^\b$username\b" &> /dev/null ;then
        w | egrep "^\b$username\b" >> /var/login.log
        echo "$username 已经登录"
        exituser
    else
        echo "$username 已经下线"
    fi
    sleep 3
done

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

#!bin/bash
lim=10
let key=$RANDOM%lim
read -p  "please input a number less than $lim: " num
until false;do
    if [ $num -le $lim &> /dev/null  ] && [ $num -ge 0  &> /dev/null ] ;then
        if [ $num -lt $key ];then
            read -p "is small,please input again: " num
        elif [ $num -gt $key ];then
            read -p "is big,please input again: " num
        else
            echo "you are right,you are very clever"
            break
        fi
    else
        read -p  "error,please input a number less than ten: " num
    fi
done


6.5 一些特殊用法

while循环的特殊用法(遍历文件的每一行): 

  while read line; do 

    循环体 

  done < /PATH/FROM/SOMEFILE 

依次读取/PATH/FROM/SOMEFILE文件中的每一行,且将行赋值给变量line 

练习 扫描/etc/passwd文件每一行,如发现GECOS字段为空,则填充用户名和单位电话为62985600,并提示该用户的GECOS信息修改成功。

#!/bin/bash
phone=" phone number is 62985600"
pathname=/etc/passwd
while read line;do
    name=echo $line|cut -d: -f1
    b=echo $line | cut -d: -f5|wc -c
    if [ $b -eq 1  ] ;then
        chfn -f $name -p $phone $name &>/dev/null && echo "$name信息修改成功" || echo "$name信息修改失败"
    fi
done < $pathname

双小括号方法,即((…))格式,也可以用于算术运算 

双小括号方法也可以使bash Shell实现C语言风格的变量操作 #I=10 #((I++)) 

for循环的特殊格式: 

for ((控制变量初始化;条件判断表达式;控制变量的修正表达式)) do 

  循环体 

done 

控制变量初始化:仅在运行到循环代码段时执行一次 

控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算 ,而后再做条件判断

6.6 select 循环与菜单

select variable in list

 do

    循环体命令

 done

select 循环主要用于创建菜单,按数字顺序排列的菜单项将显示在标准错误上,并显示PS3提示符等待用户输入

用户输入菜单列表中的某个数字,执行相应的命令

用户输入被保存在内置变量REPLY中

select是个无限循环,因此要记住用break命令退出循环,或用exit命令终止脚本,也可以按Ctrl+c退出循环

select经常和case联合使用

与for循环类似,可以省略in list,此时使用位置参数

比如

#!/bin/bash
PS3="please input your chose:"
list="start stop restart status exit"
select k in $list
do
    case $k in
        start)
            echo start
            ;;
        stop)
            echo stop
            ;;
        restart)
            echo restart
            ;;
        status)
            echo status
            ;;
        exit)
            echo exit
            ;;
        *)
            break
            ;;
    esac
done

blob.png

linux之基础shell脚本编程1  基础变量赋值

linux之基础shell脚本编程3 函数数组

linux之基础shell脚本编程4 字符串操作,变量赋值,配置用户环境 

类似文章