shell(shell變量、條件表達式、流程控制)


本章內容:

  1. 變量
  2. 運算
  3. if語句
  4. for語句
  5. while語句
  6. break、continue
  7. 實例

shell變量

1、shell變量簡介

變量是任何一種編程語言都必不可少的組成部分,變量用來存放各種數據。腳本語言在定義變量時通常不需要指明類型,直接賦值就可以,Shell 變量也遵循這個規則。

在 Bash shell 中,每一個變量的值都是字符串,無論你給變量賦值時有沒有使用引號,值都會以字符串的形式存儲;這意味着,Bash shell 在默認情況下不會區分變量類型,即使你將整數和小數賦值給變量,它們也會被視為字符串,這一點和大部分的編程語言不同。

2、定義變量

Shell 常用三種定義變量的方式:

variable=value
variable='value'    #所見即所得
variable="value"   #進行轉義
variable=`cat test`  #執行命令將命令輸出賦值給變量  

Shell 變量的命名規范和大部分編程語言都一樣:

  • 變量名由數字、字母、下划線組成;
  • 必須以字母或者下划線開頭;
  • 不能使用 Shell 里的關鍵字(通過 help 命令可以查看保留關鍵字)。

3、使用變量

╭─root@localhost.localdomain ~  
╰─➤  aa="cjk"
╭─root@localhost.localdomain ~  
╰─➤  echo $aa
cjk
╭─root@localhost.localdomain ~  
╰─➤  echo ${aa}   #推薦給所有變量加上花括號{ },這是個良好的編程習慣
cjk

4、刪除變量

使用 unset 命令可以刪除變量

╭─root@localhost.localdomain ~  
╰─➤  aa="cjk"
╭─root@localhost.localdomain ~  
╰─➤  echo ${aa}
cjk
╭─root@localhost.localdomain ~  
╰─➤  unset aa   #unset 命令不能刪除只讀變量
╭─root@localhost.localdomain ~  
╰─➤  echo ${aa}

5、變量類型

運行shell時,會同時存在三種變量:

局部變量

局部變量在腳本或命令中定義,僅在當前shell實例中有效,其他shell啟動的程序不能訪問局部變量。

環境變量

所有的程序,包括shell啟動的程序,都能訪問環境變量,有些程序需要環境變量來保證其正常運行。必要的時候shell腳本也可以定義環境變量。

shell變量

shell變量是由shell程序設置的特殊變量。shell變量中有一部分是環境變量,有一部分是局部變量,這些變量保證了shell的正常運行

6、系統變量

在命令行提示符直接執行 env、set 查看系統或環境變量。env 顯示用戶環境變量,set 顯示 Shell 預先定義好的變量以及用戶變量。可以通過 export 導出成用戶變量。一些寫 Shell 腳本時常用的系統變量

系統變量名 系統變量意識
$SHELL 默認 Shell
$HOME 當前用戶家目錄
$IFS 內部字段分隔符
$LANG 默認語言
$PATH 默認可執行程序路徑
$PWD 當前目錄
$UID 當前用戶 ID
$USER 當前用戶
$HISTSIZE 歷史命令大小,可通過 HISTTIMEFORMAT 變量設置命令執行時間
$RANDOM 隨機生成一個 0 至 32767 的整數
$HOSTNAME 主機名

生成8位隨機數:echo "$RANDOM"|md5sum|cut -c 1-8

7、普通變量和環境變量

  • 普通變量定義:VAR=value
  • 臨時環境變量定義:export VAR=value
  • 變量引用:$VAR
  • 區別:Shell 進程的環境變量作用域是 Shell 進程,當 export 導入到系統變量時,則作用域是 Shell 進程及其 Shell 子進程,另開shell無效。

8、特殊變量列表(shell變量)

變量 含義
$0 當前腳本的文件名
$n 傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是$1,第二個參數是$2。
$# 傳遞給腳本或函數的參數個數。
$* 傳遞給腳本或函數的所有參數。
$? 上個命令的退出狀態,或函數的返回值,成功會返回 0,失敗返回非0
$$ 當前Shell進程ID,對於 Shell 腳本,就是這些腳本所在的進程ID

實例:

╭─root@localhost.localdomain ~  
╰─➤  vim test.sh
...
#!/bin/bash

echo "File Name: $0"

echo "First Parameter : $1"

echo "First Parameter : $2"

echo "Quoted Values: $@"

echo "Quoted Values: $*"

echo "Total Number of Parameters : $#"
...
╭─root@localhost.localdomain ~  
╰─➤  bash test.sh  hello cjk touch
File Name: test.sh
First Parameter : hello
First Parameter : cjk
Quoted Values: hello cjk touch
Quoted Values: hello cjk touch
Total Number of Parameters : 3
╭─root@localhost.localdomain ~  
╰─➤  echo $?                      
0
╭─root@localhost.localdomain ~  
╰─➤  ddd ddd
zsh: command not found: ddd
╭─root@localhost.localdomain ~  
╰─➤  echo $?    
127

shift 命令 將參數向前移一位
shift n 向前移n位


shell條件表達式與運算符

9、條件表達式

表達式 實例
[ expression ] [ 1 -eq 1 ]
[[ expression ]] [[ 1 -eq 1 ]]
test expression test 1 -eq 1 ,等同於[]

注意:括號中的表達式前后都有空格,否則會報錯!

╭─root@localhost.localdomain ~  
╰─➤  [ 1 -eq 1 ] && echo "true" || echo "false"
true
╭─root@localhost.localdomain ~  
╰─➤  [ 1 -eq 2 ] && echo "true" || echo "false"
false
╭─root@localhost.localdomain ~  
╰─➤  [1 -eq 2] && echo "true" || echo "false" 
zsh: bad pattern: [1

10、整數比較符

比較符 描述 實例
-eq, equal 等於 [ 1 -eq 1 ] 為true
-ne, not equal 不等於 [ 1 -ne 1 ] 為false
-gt, greate than 大於 [ 1 -gt 1 ] 為false
-lt, lesser than 小於 [ 1 -lt 1 ] 為false
-ge, greate or equal 大於或者等於 [ 1 -ge 1 ] 為true
-le, lesser or equal 小於或者等於 [ 1 -le 1 ] 為true

11、字符串比較符

運算符 描述 實例
== 等於 [ “a” == “a” ] 為true
!= 不等於 [ “a” != “a” ] 為false
-n 字符串長度不等於 0 為真 VAR1=1;VAR2=””
[ -n “$VAR1” ]為 true
[ -n “$VAR2” ]為 false
-z 字符串長度等於 0 為真 VAR1=1;VAR2=””
[ -z “$VAR1” ]為false
[ -z “$VAR2” ]為 true

注意:使用-n 判斷字符串長度時,變量要加雙引號,養成好習慣,字符串比較時都加上雙引號

12、文件測試

測試符 描述 實例
-e 文件或者目錄存在為真 [ -e path ] path 存在為 true
-f 文件存在為真 [ -f file_path ] 文件存在為 true
-d 目錄存在為真 [ -d dir_path ] 目錄存在為 true
-r 有讀權限為真 [ -r file_path ]file_path有讀權限為真
-w 有寫權限為真 [ -w file_path ]file_path有寫權限為真
-x 有執行權限為真 [ -x file_path ]file_path有執行權限為真
-s 文件存在且不為空為真 [-s file_path]file_path存在且不為空為真

13、布爾運算符

運算符 描述 實例
非關系,條件結果取反 [ ! 1 -eq 2 ]為true
-a 和關系,在[]表達式中使用 [ 1 -eq 1 -a 2 -eq 2 ]為true
兩者都為真才為真
-o 或關系,在[]表達式中使用 [ 1 -eq 1 -o 2 -eq 1 ]為true
兩者有一真則為真

14、邏輯判斷符

判斷符 描述 實例
&& 邏輯和,在[[]]表達式中或判斷表達式是否為真時使用 [[ 1 -eq 1 && 2 -eq 2 ]]為 true
[ 1 -eq 1 ] && echo ‘true’
如果&&前面的表達式為true則執行后面的
|| 邏輯或,在[[]]表達式中或判斷表達式是否為真時使用 [[ 1 -eq 1 || 2 -eq 1 ]]為 true
[ 1 -eq 2 ] || echo ‘true’
如果||前面的表達式為false則執行后面的

15、整數運算符

運算符 描述
+ 加法
減法
* 乘法
/ 除法
% 取余
運算表達式 實例
$(()) $((1+1))
$[] $[]

16、其他運算符

命令 描述 實例
let 賦值並運算 let x++;echo $x 每執行一次 x 加 1
let y–;echo $y 每執行一次 y 減 1
let x+=2 每執行一次 x 加 2
let x-=2 每執行一次 x 減 2
expr 乘法*需要\轉義"\*" expr 1 \* 2 運算符兩邊必須有空格
expr\( 1 + 2\) \* 2 使用雙括號時要轉義

if語句

if語句用exit結束

1.1單分支

if 條件表達式 ;then

    命令

fi

實例:

#!/bin/bash
read -p "請輸入數字" num
if [ $num -lt 10 ] ;then
        echo "${num}是數字兩位數"
fi
...

╭─root@localhost.localdomain ~  
╰─➤  bash test.sh
請輸入數字3
3是數字一位數

1.2、多分支

if 條件表達式 ;then
    命令
else
    命令
fi

實例:

#!/bin/bash
read -p "請輸入數字" num
if [ $num -gt 9 -a $num -lt 100 ] ;then
        echo "${num}是數字兩位數"
else
        echo "${num}不是數字兩位數"
fi
...

╭─root@localhost.localdomain ~  
╰─➤  bash test.sh 
請輸入數字56
56是數字兩位數
╭─root@localhost.localdomain ~  
╰─➤  bash test.sh
請輸入數字222
222不是數字兩位數

1.3、多分支

if 條件表達式 ;then
    命令
elif 條件表達式 ;then
    命令
else
    命令
fi

實例:

#!/bin/bash
num=`echo $RANDOM`
if [ $num -lt 1000 ];then
        echo "$num小於1000"
elif [ $num -ge 1000 -a $num -lt 2000 ];then
        echo "$num大於等於1000,小於2000"
elif [ $num -ge 2000 -a $num -lt 3000 ];then
        echo "$num大於等於2000,小於3000"
elif [ $num -ge 3000 -a $num -lt 4000 ];then
        echo "$num大於等於3000,小於4000"
else
        echo "$num大於等於4000"
fi
...
╭─root@localhost.localdomain ~  
╰─➤  bash test.sh
24497大於等於4000
╭─root@localhost.localdomain ~  
╰─➤  bash test.sh
20763大於等於4000

for 循環

for  變量名  in  取值列表

do

    命令

done

實例:

#!/bin/bash
. /etc/init.d/functions
ip=192.168.80.
for i in `seq 10`
do
        if ping -c 1 -w 1 $ip$i &>/dev/null;then
                echo -n " $ip$i"    #-n:作用不換行  ;$ip前有空格
                success
                echo " "
                sleep 1
        else
                echo -n " $ip$i"
                failure
                echo " "
                sleep 1
        fi
done

...
╭─root@localhost.localdomain ~  
╰─➤  bash test.sh
 192.168.80.1                                              [  OK  ]
 192.168.80.2                                              [  OK  ]
 192.168.80.3                                              [  OK  ]
 192.168.80.4                                              [  OK  ]
 192.168.80.5                                              [FAILED]
 192.168.80.6                                              [FAILED]
 192.168.80.7                                              [FAILED]
 192.168.80.8                                              [FAILED]
 192.168.80.9                                              [FAILED]
 192.168.80.10                                             [FAILED]

while循環

while 條件表達式 ; do

      命令

done

3.1、一般循環

當條件表達式為 false 時,終止循環

實例:

#!/bin/bash
N=0
while [ $N -lt 5 ]; do
        echo $N
        let N++
done
...
╭─root@localhost.localdomain ~  
╰─➤  bash test1.sh
0
1
2
3
4

3.2、死循環

條件表達式為 true,將會產生死循環

#!/bin/bash
while true ;do
        echo "hello"
        sleep 1
done

...
╭─root@localhost.localdomain ~  
╰─➤  bash test2.sh
hello
hello
hello
hello
hello
^C
  • 命令行中輸入 nohup bash naolie.sh & 即可在后台持續運行該腳本

break和continue語句

  • continue 與 break 語句只能循環語句中使用;
  • break:終止循環,運行針跳至done后;
  • continue :跳出當前循環,運行針跳至do后,開始下一循環;

演示:
break語句

#!/bin/bash
N=0
while [ $N -lt 10 ]; do
        let N++
        if [ $N -eq 5 ]; then
                break
        fi
        echo $N
done
...
╭─root@localhost.localdomain ~  
╰─➤  bash test1.sh
1
2
3
4

continue語句

#!/bin/bash
N=0
while [ $N -lt 10 ]; do
        let N++
        if [ $N -eq 5 ]; then
                continue
        fi
        echo $N
done
...
╭─root@localhost.localdomain ~  
╰─➤  bash test1.sh
1
2
3
4
6
7
8
9
10

實例拓展:

實例1:

#!/bin/bash
echo "主機名:`hostname`"
echo "IP地址:`ip a | grep "global" | cut -d "/" -f 1 | cut -d "t" -f 2 | tr -d " "`"
echo "操作系統版本:`cat /etc/redhat-release`"
echo "內核版本:`uname -r`"
echo "CPU信息:`lscpu | grep -i "Model name" | cut -c "24-69"`"
echo "內存總大小:`free -h | grep "Mem" | cut -d "M" -f 2 | tr -d "em: "`M"
...
╭─root@localhost.localdomain ~  
╰─➤  bash test6.sh
主機名:localhost.localdomain
IP地址:192.168.80.3
操作系統版本:CentOS Linux release 7.3.1611 (Core) 
內核版本:3.10.0-514.el7.x86_64
CPU信息:Intel(R) Core(TM) i5-4210M CPU @ 2.60GHz
內存總大小:976M
...

實例二:

#!/bin/bash
sum=0
for i in `find / -type f -a -name "*.sh"`
do
        size=`ls -l $i | cut -d " " -f 5`
        let sum+=size
done
echo ".sh結尾的總大小$(($sum/1024))kb"
...
╭─root@localhost.localdomain ~  
╰─➤  bash test7.sh
.sh結尾的總大小1098kb

實例三:創建100個用戶並設置6位隨機密碼

[root@du ~]# cat test9.sh
#!/bin/bash
#!/bin/bash
for i in `seq 10`
do
    useradd user$i
    pass=`echo $RANDOM | md5sum | cut -c 1-6`
    echo "$pass" | passwd --stdin "user$i"
    echo -e "賬戶:user$i\n密碼:$pass" >> /root/passwd
done

##執行結果:

[root@du ~]# cat passwd
賬戶:user1
密碼:69a70a
賬戶:user2
密碼:444c02
賬戶:user3
密碼:6b381f
賬戶:user4
密碼:28d8fd

實例四:找出100以內的質數

#!/bin/bash
for i in `seq 100`
do
    for((j=2;j<i;j++))
    do
         [ $((i%j)) -eq 0 ] &&  break
    done
         [ $j -eq $i ] &&   echo $i
done


## 執行
╭─root@localhost.localdomain ~  
╰─➤  bash test.sh 
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97

實例五:逐行讀取文件

#!/bin/bash
cat $1 | while read line
do
echo “$line”
sleep 1
done

## 執行

╭─root@localhost.localdomain ~  
╰─➤  bash readtest.sh /etc/passwd
“root:x:0:0:root:/root:/bin/zsh”
“bin:x:1:1:bin:/bin:/sbin/nologin”
“daemon:x:2:2:daemon:/sbin:/sbin/nologin”
“adm:x:3:4:adm:/var/adm:/sbin/nologin”
“lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin”
^C#  

實例六:shell腳本工整化輸出,表格形式輸出
摘自:https://blog.csdn.net/qq_41228463/article/details/80720772

#!/bin/bash
table=""
#設置行,可以是表頭,也可以是表格內容。
#如果是表格內容,“—”表示空值
function setRow(){
    value=$*
    table=${table}"|${value// /#|}#|\n"
}

#行分隔線
#入參:表格的列數。如表格有5列,則入參為5
function splitLine(){
    local num=`expr $1 + 2`
    split=`seq -s '+#' $num | sed 's/[0-9]//g'`    # 生成連續個的+#
    table=${table}"${split}\n"
}

#繪制表格
#入參:table
function setTable(){
    echo -e $1|column -s "#" -t|awk '{if($0 ~ /^+/){gsub(" ","-",$0);print $0}else{print $0}}'
}
if [ "$SHLVL" -eq "2" ]
then
   table=""
    splitLine 3
    setRow "姓名" "性別" "年齡"
    splitLine 3
    setRow "Tom" "male" "10"
    setRow "Nacy" "female" "-"
    splitLine 3
    setTable ${table}
fi
##輸出結果

#bash test.sh
+------+--------+------+--
|姓名  |性別    |年齡  |
+------+--------+------+--
|Tom   |male    |10    |
|Nacy  |female  |-     |
+------+--------+------+--


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM