shell條件判斷和流程控制語句If
偶遇4774 已關(guān)注
2019.05.31 15:59* 字?jǐn)?shù) 1230 閱讀 1評(píng)論 0喜歡 0
1、read 命令鍵盤讀取變量的值
從鍵盤讀取變量的值,通常用在shell腳本中與用戶進(jìn)行交互的場(chǎng)合,此命令可以一次性讀取多個(gè)值,變量和輸入值都需要使用空格隔開,如果沒有指定變量名,讀取的數(shù)據(jù)將被自動(dòng)賦值給特定的變量REPLY
read命令參數(shù)
read 命令
-s ?將輸入的字符隱藏起來
-p ?設(shè)置提示信息、或用echo –n “…“來給出提示符
-t ? 設(shè)置輸入等待時(shí)間,單位默認(rèn)為秒
-n ?設(shè)置輸入的字符限制
-r ? 能夠支持特殊字符
- read 從鍵盤讀入數(shù)據(jù),賦給變量
例 1:
[root@web02 ~]# read a b
123 456
[root@web02 ~]# echo $a $b
123 456
例 2:read -s passwd 將輸入的東西隱藏起來,值賦給passwd.用在:用戶隱藏密碼信息
[root@web02 ~]# read -s passwd
[root@web02 ~]# echo $passwd
隱藏信息
例 3:read 綜合參數(shù)實(shí)踐
[root@web02 ~]# read -s -t 6 -n 6 -r -p "請(qǐng)輸入密碼:" passwd
請(qǐng)輸入密碼:
[root@web02 ~]# echo $passwd
12%$&*
例1:從標(biāo)準(zhǔn)輸入讀取一行并賦值給變量passwd
[root@web02 ~]# read passwd
例2:讀取多個(gè)值,從標(biāo)準(zhǔn)輸入讀取一行,直至遇到第一個(gè)空白符或換行符。把用戶鍵入的第一個(gè)詞存到變量first中,把該行的剩余部分保存到變量last中
[root@web02 ~]# read firt last
aaaa bbbb
例3:read -s passwd 將你輸入的東西隱藏起來,值賦給passwd。這個(gè)用戶隱藏密碼信息
[root@web02 ~]# read -s passwd
[root@web02 ~]# echo $passwd
123456
例4:輸入的時(shí)間限制
[root@web02 ~]# read -t 2 time #超過兩秒沒有輸入,直接退出
例5:輸入的長(zhǎng)度限制
[root@web02 ~]# read -n 2 test #最多只接受2個(gè)字符
例6:使用-r參數(shù)輸,允許讓輸入中的內(nèi)容包括:空格、/、\、 ?等特殊字符串。
[root@web02 ~]# read -r line
sdf sdf / sdfs /n
[root@web02 ~]# echo $line
sdf sdf / sdfs /n
例7:-p 用于給出提示符,在前面的例子中我們使用了echo –n “…“來給出提示符
方法1:
[root@web02 ~]# read -p "please input: " pass
please input: 123456
[root@web02 ~]# echo $pass
123456
方法2:
[root@web02 ~]# echo -n "please input: " ; read pass
please input: 123456
[root@web02 ~]# echo $pass
123456
例8:read 綜合實(shí)例
[root@web02 ~]# vim test-read.sh #寫入以下內(nèi)容
#!/bin/bash
read -p "請(qǐng)輸入姓名:" NAME
read -p "請(qǐng)輸入年齡:" AGE
read -p "請(qǐng)輸入性別:" SEX
cat<<eof
*********************
你的基本信息如下:
姓名: $NAME
年齡:$AGE
性別:$SEX
********************
eof
[root@web02 ~]# sh test-read.sh
請(qǐng)輸入姓名:oldboy
請(qǐng)輸入年齡:111
請(qǐng)輸入性別:man
*********************
你的基本信息如下:
姓名: oldboy
年齡:111
性別:man
2、流程控制語句if
-
2.1、單分支語法格式:
if 條件
then
commands
fi
單分支if語句流程圖:image注:根據(jù)我們的命令退出碼來進(jìn)行判斷(echo $? =0),如果是0,那么就會(huì)執(zhí)行then后面的命令
例1:
[root@web02 ~]# vim if-1.sh
#!/bin/bash
if ls /mnt
then
echo "it's ok"
fi
[root@web02 ~]# bash !$
bash if-1.sh
CentOS_BuildTag GPL LiveOS RPM-GPG-KEY-CentOS-7
EFI images Packages RPM-GPG-KEY-CentOS-Testing-7
EULA isolinux repodata TRANS.TBL
it's ok
-
2.2、雙分支if語句
語法格式:
if command ; then
commands
else
commands
fi
雙分支if語句圖:

例2:
[root@web02 ~]# cat if-2.sh
#!/bin/bash
if grep root /etc/passwd ; then
echo "it's ok"
else
"it's err"
fi
[root@web02 ~]# sh if-2.sh
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
it's ok
例3:
[root@web02 ~]# cat if-3.sh
#!/bin/bash
if grep xuegod /etc/passwd ;then
echo "it's ok"
else
echo "it's err"
fi
[root@web02 ~]# sh if-3.sh
it's err
-
2.3、多分支if語句
語法結(jié)構(gòu):
if 條件測(cè)試操作1 ; then
commands
elif 條件測(cè)試操作2 ; then
commands
elif 條件測(cè)試操作3 ; then
commands
.......
else
commands
fi
多分支if語句圖:

例4:判斷用戶在系統(tǒng)中是否存在,是否有家目錄
[root@web02 ~]# cat if-4.sh
#!/bin/bash
read -p "input a user:" tu
if grep $tu /etc/passwd ; then
echo "the user $tu exists on this system"
elif ls -d /home/$tu ; then
echo "the user $tu not exists on this system"
echo "$tu has a home directory"
else
echo "the user $tu not exists on this system"
echo "$tu not has a direcotry"
fi
[root@web02 ~]# sh if-4.sh
Input a user: hr
chrony:x:994:990::/var/lib/chrony:/sbin/nologin
hr:x:1000:1000:hr:/home/hr:/bin/bash
the user hr exists on this system
[root@web02 ~]# sh if-4.sh
Input a user: xuegod
/home/xuegod
xuegod has a directory
3、test測(cè)試命令
Shell中的 test 命令用于檢查某個(gè)條件是否成立,它可以進(jìn)行數(shù)值、字符和文件三個(gè)方面的測(cè)試格式
test 測(cè)試條件
如果結(jié)果是對(duì)的,也叫結(jié)果為真,用$?=0表示,反之為假,用非0表示
3.1、數(shù)值比較用
| 參數(shù) | 說明 | 示例 |
|---|---|---|
| -eq | 等于則為真 | [ “[圖片上傳失敗...(image-688b88-1559728118721)] |
b” ] |
| -ne | 不等于則為真 | [ “[圖片上傳失敗...(image-2e857f-1559728118721)]
b” ] |
| -gt | 大于則為真 | [ “[圖片上傳失敗...(image-dfa06f-1559728118721)]
b” ] |
| -ge | 大于等于則為真 | [ “[圖片上傳失敗...(image-5cac2c-1559728118721)]
b” ] |
| -lt | 小于則為真 | [ “[圖片上傳失敗...(image-804bd5-1559728118721)]
b” ] |
| -le | 小于等于則為真 | [ “[圖片上傳失敗...(image-a810f1-1559728118721)]
b” ] |
例1:比較大小
[root@web02 ~]# cat test1.sh
#!/bin/bash
if test 2 -eq 1 ; then
echo ok
else
echo err
fi
if [ 2 -eq 2 ] ; then
echo ok
else
echo err
fi
例2: 比較整數(shù)大小
[root@web02 ~]# cat test2.sh
#!/bin/bash
read -p "input var1 var2:" var1 var2
if [ $var1 -gt $var2 ] ; then
echo "$var1 > $var2"
elif [ $var1 -lt $var2 ] ; then
echo "$var1 < $var2"
else
echo "$var1 = $var2"
fi
注意:在做數(shù)值比較時(shí),只能用整數(shù)
3.2、字符串比較用
| 參數(shù) | 說明 | 示例 |
|---|---|---|
| == | 等于則為真 | [ “[圖片上傳失敗...(image-f1a912-1559728118721)] |
b” ] |
| != | 不相等則為真 | [ “[圖片上傳失敗...(image-9384e1-1559728118721)]
b” ] |
| -z 字符串 | 字符串的長(zhǎng)度為零則為真 | [ -z “a” ] |
| str1 > str2 | str1大于str2為真 | [ str1 > str2 ] |
| str1 < str2 | str1小于str2為真 | [ str1 < str2 ] |
例1:根據(jù)用戶名判斷是否是超級(jí)管理員
[root@web02 ~]# cat test3.sh
#!/bin/bash
read -p "input your name: " name
if [ $name == "root" ] ; then
echo "you are super administrator"
else
echo "You are a general user"
fi
[root@web02 ~]# bash test3.sh
input your name: root
you are super administrator
[root@xuegod63 ~]# bash test3.sh
input your name: mk
You are a general usero "You are a general user"
例2:在做字符串大小比較的時(shí)候,注意字符串的順序
1、大于號(hào)和小于號(hào)必須轉(zhuǎn)義,要不然SHELL會(huì)把它當(dāng)成重定向符號(hào)
2、大于和小于它們的順序和sort排序是不一樣的
3、在test比較測(cè)試中,它使用的是ASCII順序,大寫字母是小于小寫字母的;sort剛好相反
-
擴(kuò)展:
??ASCII(American Standard Code for Information Interchange,美國(guó)信息交換標(biāo)準(zhǔn)代碼)是基于拉丁字母的一套電腦編碼系統(tǒng),主要用于顯示現(xiàn)代英語和其他西歐語言。它是現(xiàn)今最通用的單字節(jié)編碼系統(tǒng),并等同于國(guó)際標(biāo)準(zhǔn)ISO/IEC 646。image
[root@web02 ~]# cat test4.sh
#!/bin/bash
var1=test
var2=Test
if [ $var1 \> $var2 ] ; then
echo "$var1 > $var2"
else
echo "$var1 < $var2"
fi
[root@web02 ~]# bash test4.sh
test > Test
3.3、文件比較用
| 參數(shù) | 說明 | 示例 |
|---|---|---|
| -e 文件名 | 如果文件或目錄存在則為真 | [ -e file ] |
| -r 文件名 | 如果文件存在且可讀則為真 | [ -r file ] |
| -w 文件名 | 如果文件存在且可寫則為真 | [ -w file ] |
| -x 文件名 | 如果文件存在且可執(zhí)行則為真 | [ -x file ] |
| -s 文件名 | 如果文件存在且至少有一個(gè)字符則為真 | [ -s file ] |
| -d 文件名 | 如果文件存在且為目錄則為真 | [ -d file ] |
| -f 文件名 | 如果文件存在且為普通文件則為真 | [ -f file ] |
| -c 文件名 | 如果文件存在且為字符型文件則為真 | [ -c file ] |
| -b 文件名 | 如果文件存在且為塊特殊文件則為真 | [ -b file ] |
| file1 -nt fle2 | 檢查file1是否比file2新 | [ file1 -nt file2 ] |
| file1 -ot file2 | 檢查file1是否比file2舊 | [ file1 -ot file2 ] |
例1:
[root@web02 ~]# vim test5.sh
#!/bin/bash
if [ -e /etc/passwd ] ; then
echo ok
else
echo err
fi
[root@web02 ~]# bash test5.sh
ok
例2:
[root@web02 ~]# test -e /etc/aaa.txt && echo ok || echo err
err
[root@web02 ~]# test -e /etc/passwd && echo ok || echo err
ok
[root@web02 ~]# test -e /etc && echo ok || echo err
ok
- 清空日志目錄
[root@web02 ~]# cat clear-log.sh
#!/bin/bash
# clear /var/log/messages
#確定當(dāng)前是root用戶
if [ $USER != "root" ];then
echo "你必須使用root用戶才能執(zhí)行腳本"
exit 10 #直接退出,并返回10
fi
#判斷文件是否存在
if [ ! -f /var/log/messages ];then
echo "文件不存在"
exit 12
fi
#保留最近100行的日志內(nèi)容
tail -100 /var/log/messages > /var/log/mesg.tmp
#日志清理
>/var/log/messages
#cat /dev/null > /var/log/messages
mv /var/log/mesg.tmp /var/log/messages
echo "Logs clean up"
注:退出碼 exit ,取值范圍是0-255
例: exit 退出bash,并返回一個(gè)值
[root@web02 ~]# ssh 192.168.1.63
root@192.168.1.63's password: 123456
Last login: Mon May 28 20:37:41 2018 from xuegod63.cn
[root@web02 ~]#
[root@web02 ~]# exit 10
登出
Connection to 192.168.1.63 closed.
[root@web02 ~]# echo $?
10
4、流程控制過程中復(fù)雜條件和通配符
- 4.1 兩個(gè)條件都為真或有一個(gè)為真就執(zhí)行
判斷第一種:
if [ 條件判斷一 ] && (||) [ 條件判斷二 ]; then
命令一
elif [ 條件判斷三 ] && (||) [ 條件判斷四 ]; then
命令二
else
執(zhí)行其它
fi
判斷第二種
if [條件判斷一 -a (-o) 條件判斷二 -a (-o) 條件判斷三]; then
elif [條件判斷三 -a (-o) 條件判斷四 ]; then
else
執(zhí)行其它
fi
判斷第三種
if [[條件判斷一 && (||) 條件判斷二 ]]; then
elif [[ 條件判斷三 && (||) 條件判斷四 ]]; then
else
執(zhí)行其它
fi
例1:設(shè)置umask
參考:
[root@web02 ~]# vim /etc/profile
59 if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
60 umask 002
61 else
62 umask 022
63 fi
實(shí)操:
[root@web02 ~]# vim umask.sh
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
echo "umask 002"
else
echo "i am root :umask 022"
fi
[root@web02 ~]# bash umask.sh
i am root :umask 022
例2:[[ 。。。 ]]和[ 。。。]的區(qū)別
[[… ]] 運(yùn)算符是[… ]運(yùn)算符的擴(kuò)充;[[… ]]能夠支持 *,< 、>等符號(hào)且不需要轉(zhuǎn)義符
例1:
[root@web02 ~]# if [[ $USER == r* ]] ; then echo "hello,$USER" ; else echo $USER not ; fi
hello,root
注: $USER == r*對(duì)比時(shí), r* 表示以r開頭的任意長(zhǎng)度字符串,這樣就包括root
當(dāng)只有一個(gè)[] 方括號(hào)時(shí):
[root@web02 ~]# if [ $USER == r* ] ; then echo "hello,$USER" ; else echo $USER not ; fi
root not
#對(duì)比時(shí)r* ,就表示兩個(gè)字符串 r*
也可以這樣寫:
[root@web02 ~]# if [[ $USER == [a-z]oot ]] ; then echo "hello,$USER" ; else echo $USER not ; fi
- [[ 。。。 ]]和[ 。。。]的區(qū)別匯總:
1、所有的字符與邏輯運(yùn)算符直接用“空格”分開,不能連到一起。
2、在[… ]表達(dá)式中,常見的> 、<需要加轉(zhuǎn)義符\,大小比較
3、進(jìn)行邏輯運(yùn)算符&& 、||比較時(shí);如果用的[ ]符號(hào),則用在外面,如[… ] && [… ] || [ …]如果在[…]里面進(jìn)行邏輯與或的比較,則用-a、-o進(jìn)行表示,如[ x = y –a x < z –o x > m ]
4、[[… ]] 運(yùn)算符只是[… ]運(yùn)算符的擴(kuò)充;能夠支持< 、>符號(hào)運(yùn)算不需要轉(zhuǎn)義符;它還是以字符串比較大小。里面支持邏輯運(yùn)算符 || 、 && , 不再使用-a 、-o
5、[[…]] 用 && 而不是 -a 表示邏輯“與”;用 || 而不是 -o表示邏輯“或”
6、[[… ]]可以進(jìn)行算術(shù)擴(kuò)展,而[ ... ]不可以
7、[[...]]能用正則,而[...]不行
8、雙括號(hào)(( ))用于數(shù)學(xué)表達(dá)式
9、雙方括號(hào)號(hào)[[ ]]用于高級(jí)字符串處理,比如“模糊匹配”
4.2 shell中的通配符
- shell常見通配符:
| 字符 | 含義 | 實(shí)例 |
|---|---|---|
| * | 匹配 0 或多個(gè)字符 | a*b a與b之間可以有任意長(zhǎng)度的任意字符, 也可以一個(gè)也沒有, 如aabcb, axyzb, a012b, ab。 |
| ? | 匹配任意一個(gè)字符 | a?b a與b之間必須也只能有一個(gè)字符, 可以是任意字符, 如aab, abb, acb, a0b。 |
| [list] | 匹配 list 中的任意單一字符 | a[xyz]b a與b之間必須也只能有一個(gè)字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb。 |
| [!list] | 匹配 除list 中的任意單一字符 | a[!0-9]b a與b之間必須也只能有一個(gè)字符, 但不能是阿拉伯?dāng)?shù)字, 如axb, aab, a-b。 |
| [c1-c2] | 匹配 c1-c2 中的任意單一字符 如:[0-9] [a-z] | a[0-9]b 0與9之間必須也只能有一個(gè)字符 如a0b, a1b... a9b。 |
| {string1,string2,...} | 匹配 sring1 或 string2 (或更多)其一字符串 | a{abc,xyz,123}b a與b之間只能是abc或xyz或123這三個(gè)字符串之一 |
例:
[root@web02 ~]# ls /etc/*.conf
[root@web02 ~]# ls /etc/???.conf
/etc/nfs.conf /etc/sos.conf /etc/yum.conf
[root@web02 ~]# touch /opt/a{1,2,3}.txt
[root@web02 ~]# ls /opt/a[123].txt
/opt/a1.txt /opt/a2.txt /opt/a3.txt
[root@web02 ~]# ls /opt/a[1,2,3].txt
[root@web02 ~]# ls /opt/a[13].txt
/opt/a1.txt /opt/a3.txt
5、實(shí)戰(zhàn)-3個(gè)shell腳本實(shí)戰(zhàn)
- 實(shí)戰(zhàn)1:編寫腳本檢查服務(wù)器運(yùn)行狀態(tài)
[root@web02 ~]# vim status.sh
#!/bin/bash
if [ $# -ge 1 ] ; then
systemctl status $1 > /dev/null
if [ $? -eq 0 ] ; then
echo "$1 服務(wù)正在運(yùn)行"
else
systemctl start $1
fi
else
echo "執(zhí)行腳本的格式"
echo "sh $0 服務(wù)名"
fi
- 實(shí)戰(zhàn)2:根據(jù)學(xué)生的成績(jī)判斷 學(xué)生的優(yōu)劣
[root@web02 ~]# vim check_cj.sh
#!/bin/bash
read -p "請(qǐng)輸入你的成績(jī) " cj
if [ $cj -ge 0 ] && [ $cj -le 59 ] ;then
echo "補(bǔ)考"
elif [ $cj -ge 60 ] && [ $cj -le 70 ] ;then
echo "良好"
elif [ $cj -ge 71 ] && [ $cj -le 85 ] ;then
echo "好"
elif [ $cj -ge 86 ] && [ $cj -le 100 ] ;then
echo "優(yōu)秀"
else
echo "成績(jī)的有效范圍是0-100之間"
fi
- 實(shí)戰(zhàn)3:每周一晚上3:00 ,備份數(shù)據(jù)庫服務(wù)器上webdb庫的所有數(shù)據(jù)到系統(tǒng)的/mysqlbak目錄里,使用系統(tǒng)日期做備份文件名
[root@web02 ~]# vim mysqlbak.sh
#!/bin/bash
baknamefile=`date +%Y-%m-%d`
bakdir=/mysqlbak
user=root
password=123
dbname=webdb
[ -e $bakdir ] || mkdir $bakdir
mysqldump -u$user -p$password --flush-logs $dbname > $bakdir/${baknamefile}-webdb.sql
因?yàn)閙ysql咱們還沒有學(xué),這里以/etc目錄來做實(shí)驗(yàn):
[root@xuegod63 ~]# vim etcbak.sh
#!/bin/bash
baknamefile=`date +%Y-%m-%d`
bakdir=/etcbak
srcdir=/etc
[ -e $bakdir ] || mkdir $bakdir
tar zcvf ${bakdir}/${baknamefile}-etc.tar.gz /etc/
echo "========================"
ls -lh ${bakdir}/${baknamefile}-etc.tar.gz
echo "back etc is ok!"
[root@web02 ~]# chmod +x etcbak.sh
[root@web02 ~]# crontab -e
0 3 * * * /root/etcbak.sh 2>&1 > /dev/null
6、總結(jié):
1. read命令鍵盤讀取變量的值
2. 流程控制語句if
3. test測(cè)試命令
4. 流程控制過程中復(fù)雜條件和通配符
5. 實(shí)戰(zhàn)-3個(gè)shell腳本實(shí)戰(zhàn)

