- ver: 1.0
- Blog:博客園 個人
- 本文介紹了Shell常用的結構化語句。
數(shù)組
數(shù)組(Array)是若干數(shù)據(jù)的集合,其中的每一份數(shù)據(jù)都稱為元素(Element)。
Bash只支持一維數(shù)組(不支持多維數(shù)組),初始化時不需要定義數(shù)組大小,理論上可以存放無限量的數(shù)據(jù)。
與大部分編程語言類似,數(shù)組元素的下標由0開始。
Shell數(shù)組用括號來表示,元素用"空格"符號分割開。格式如下:
array_name=(ele1 ele2 ele3 ... elen)
Tips:賦值號= 兩邊不能有空格,必須緊挨著數(shù)組名和數(shù)組元素。
獲取數(shù)組中的元素要使用下標[] ,下標可以是一個整數(shù),也可以是一個結果為整數(shù)的表達式;當然,下標必須大于等于0。格式如下:
${array_name[index]}
Tips:array_name 是數(shù)組名,index 是下標。
Shell是弱類型的,它并不要求所有數(shù)組元素的類型必須相同,例如:
arr=(10 24 'ddd' 'ab22' 5)
獲取數(shù)組所有元素
使用@ 或* 可以獲取數(shù)組中的所有元素,格式如下:
${array_name[*]}
${array_name[@]}
獲取數(shù)組元素個數(shù)
使用# 來獲取數(shù)組元素的個數(shù),格式如下:
${#array_name[@]}
${#array_name[*]}
數(shù)組合并
數(shù)組合并,就是將兩個或兩個以上的數(shù)組合并成一個個數(shù)組,格式如下:
array_new=(${array1[@]} ${array2[@]}...${arrayn[@]})
array_new=(${array1[*]} ${array2[*]}...${arrayn[*]})
刪除數(shù)組元素
使用unset 關鍵字來刪除數(shù)組元素,格式如下:
unset array_name[index]
如果不寫下標,則代表刪除整個數(shù)組所有元素,格式如下:
unset array_name
實例
測試ip是否ping通
#!/usr/bin/env bash
# Author: Rohn
# Version: 1.0
# Create Time: 2020/06/13
# Test network connectivity
arr_num=(3 11 25 32 200)
for i in ${arr_num[*]}; do
ip=192.168.110.${i}
ping -c 1 $ip >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo "${ip} is ok."
else
echo "${ip} is unreachable."
fi
done
選擇結構
Shell中的選擇結構(分支結構)有兩種形式,分別是 if-else 和case-in 語句,它們都根據(jù)命令的退出狀態(tài)來判斷條件是否成立。
if-else語句
基本格式
基本結構格式:
if condition; then
statement(s)
fi
condition 是判斷條件,如果condition 成立(返回True),那么then 后邊的語句將會被執(zhí)行;如果 condition不成立(返回False),那么不會執(zhí)行任何語句。
Tips:最后必須以fi 來閉合,fi 就是if 倒過來拼寫。
if-else
如果有兩個分支,就可以使用if-else 語句,格式:
if condition; then
statement1
else
statement2
fi
如果condition 成立,那么then 后邊的 statement1 語句將會被執(zhí)行;否則,執(zhí)行else 后邊的statement2 語句。
if-elif-else
當分支比較多時,可以使用if-elif-else 結構,格式:
if condition1; then
statement1
elif condition2;then
statement2
...
else
statementn
fi
Tips:if 和elif 后邊都得跟著then 。
語句的執(zhí)行邏輯:
- 如果
condition1 成立,那么執(zhí)行statement1 ,如果不成立,則執(zhí)行elif 語句;
- 如果
elif 語句不成立,則執(zhí)行else 語句;
case-in語句
當分支較多,且判斷條件比較簡單時,推薦使用case-in 語句。格式如下:
case expression in
pattern1)
statement1
;;
pattern2)
statement2
;;
...
*)
statementn
esac
expression 表示表達式,既可以是一個變量、一個數(shù)字、一個字符串,還可以是一個數(shù)學計算表達式,或者是命令的執(zhí)行結果,只要能夠得到expression 的值就可以。
pattern 表示匹配模式,可以是一個數(shù)字、一個字符串,甚至是一個簡單的正則表達式。
case 會將expression 的值與 pattern1 、pattern2 ...patternn 逐個進行匹配:
- 如果
expression 和某個模式(比如 pattern2)匹配成功,就會執(zhí)行這模式(比如 pattern2)后面對應的所有語句(該語句可以有一條,也可以有多條),直到遇見雙分號;; 才停止;然后整個case-in 語句就執(zhí)行完了,程序會跳出整個 case-in 語句,執(zhí)行esac 后面的其它語句。
- 如果 expression 沒有匹配到任何一個模式,那么就執(zhí)行
*) 后面的語句(* 表示其它所有值),直到遇見雙分號;; 或者esac 才結束。*) 相當于多個if 分支語句中最后的else 部分。
Tips:分支*) 并不是什么語法規(guī)定,它只是一個正則表達式,* 表示任意字符串,所以不管expression 的值是什么,*) 總能匹配成功。因此,可以沒有*) 部分,如果expression 沒有匹配到任何一個模式,那么就不執(zhí)行任何操作。
除最后一個分支外(這個分支可以是普通分支,也可以是*) 分支),其它的每個分支都必須以;; 結尾,;; 代表一個分支的結束,不寫的話會有語法錯誤。最后一個分支可以寫;; ,也可以不寫,因為無論如何,執(zhí)行到esac 都會結束整個case-in 語句。
case-in 的pattern 部分支持簡單的正則表達式,具體來說,可以使用以下幾種格式:
格式 |
說明 |
* |
表示任意字符串。 |
[abc] |
表示 a、b、c 三個字符中的任意一個。比如,[15ZH] 表示 1、5、Z、H 四個字符中的任意一個。 |
[m-n] |
表示從 m 到 n 的任意一個字符。比如,[0-9] 表示任意一個數(shù)字,[0-9a-zA-Z] 表示字母或數(shù)字。 |
| |
表示多重選擇,類似邏輯運算中的或運算。比如,abc | xyz 表示匹配字符串 "abc" 或者 "xyz"。 |
用;; &終止每個條件塊,例如:
read -n 1 -p "Type a character > "
echo
case $REPLY in
[[:upper:]]) echo "'$REPLY' is upper case." ;;&
[[:lower:]]) echo "'$REPLY' is lower case." ;;&
[[:alpha:]]) echo "'$REPLY' is alphabetic." ;;&
[[:digit:]]) echo "'$REPLY' is a digit." ;;&
[[:graph:]]) echo "'$REPLY' is a visible character." ;;&
[[:punct:]]) echo "'$REPLY' is a punctuation symbol." ;;&
[[:space:]]) echo "'$REPLY' is a whitespace character." ;;&
[[:xdigit:]]) echo "'$REPLY' is a hexadecimal digit." ;;&
esac
輸出結果如下:
Type a character > a
'a' is lower case.
'a' is alphabetic.
'a' is a visible character.
'a' is a hexadecimal digit.
循環(huán)結構
循環(huán)結構語句大致分為4種:
while語句
當條件滿足時,while 重復地執(zhí)行一組語句,當條件不滿足時,就退出while 循環(huán)。格式如下:
while condition; do
statements
done
執(zhí)行流程如下:
- 先對
condition 進行判斷,如果該條件成立,就進入循環(huán),執(zhí)while 循環(huán)體中的語句,也就是do 和done 之間的語句。這樣就完成了一次循環(huán)。
- 每一次執(zhí)行到
done 的時候都會重新判斷condition 是否成立,如果成立,就進入下一次循環(huán),繼續(xù)執(zhí)行do 和done 之間的語句,如果不成立,就結束整個while 循環(huán),執(zhí)行done 后面的其它Shell 代碼。
- 如果一開始
condition 就不成立,那么程序就不會進入循環(huán)體。
死循環(huán)
格式一:
while true; do
statements
done
格式二:
while [ 1 ]; do
statements
done
until語句
until 循環(huán)當判斷條件不成立時才進行循環(huán),一旦判斷條件成立,就終止循環(huán)。
until condition; do
statements
done
until 循環(huán)的執(zhí)行流程為:
- 先對
condition 進行判斷,如果該條件不成立,就進入循環(huán),執(zhí)行until 循環(huán)體中的語句(do 和done 之間的語句),這樣就完成了一次循環(huán)。
- 每一次執(zhí)行到
done 的時候都會重新判斷condition 是否成立,如果不成立,就進入下一次循環(huán),繼續(xù)執(zhí)行循環(huán)體中的語句,如果成立,就結束整個 until 循環(huán),執(zhí)行done 后面的其它Shell 代碼。
for語句
C語言風格的 for 循環(huán)
格式如下:
for((exp1; exp2; exp3)); do
statements
done
exp1 、exp2 、exp3 是三個表達式,其中exp2 是判斷條件,for 循環(huán)根據(jù)exp2 的結果來決定是否繼續(xù)下一次循環(huán);
它的運行過程為:
- 先執(zhí)行
exp1 。
- 再執(zhí)行
exp2 ,如果它的判斷結果是成立的,則執(zhí)行循環(huán)體中的語句,否則結束整個for 循環(huán)。
- 執(zhí)行完循環(huán)體后再執(zhí)行
exp3 。
- 重復執(zhí)行2、3步驟,直到
exp2 的判斷結果不成立,就結束循環(huán)。
for-in循環(huán)
格式如下:
for variable in value_list; do
statements
done
variable 表示變量,value_list 表示取值列表。
每次循環(huán)都會從value_list 中取出一個值賦給變量 variable ,然后進入循環(huán)體(do 和done 之間的部分),執(zhí)行循環(huán)體中的statements 。直到取完value_list 中的所有值,循環(huán)就結束了。
value_list :
for i in 1 2 3 'dd';do echo $i;done
# 求1到10的和
sum=0
for i in {1..10}; do
sum=$((sum+i))
done
echo $sum
# 求100以內(nèi)偶數(shù)的和
for i in $(seq 2 2 100); do
sum=$((sum+i))
done
echo $sum
# 打印當前路徑.log結尾的文件
for i in *.log; do echo $i;done
Tips:若當前路徑無.log結尾的文件,則會打印*.log
for i in $@; do
sum=$((sum+i))
done
echo $sum
select-in語句
select-in 循環(huán)用來增強交互性,它可以顯示出帶編號的菜單,用戶輸入不同的編號就可以選擇不同的菜單,并執(zhí)行不同的功能,非常適合終端(Terminal)這樣的交互場景。格式如下:
select variable in value_list; do
statements
done
variable 表示變量,value_list 表示取值列表。
例如:
echo "選擇你要學習的科目:"
select i in 'Linux' 'Python' 'Java' 'C++' 'PHP'; do
echo "你選擇了${i}。"
done
結果如下:
選擇你要學習的科目:
1) Linux
2) Python
3) Java
4) C++
5) PHP
#? 5
你選擇了PHP。
#? 2
你選擇了Python。
#? 666
你選擇了。
Tips:select 是死循環(huán),輸入空值或者輸入的值無效,都不會結束循環(huán),只有遇到break 語句,或者按下Ctrl+D 組合鍵才能結束循環(huán)。
例如:
echo "選擇你要學習的科目:"
select i in 'Linux' 'Python' 'Java' 'C++' 'PHP'; do
echo "你選擇了${i}。"
break
done
結果如下:
選擇你要學習的科目:
1) Linux
2) Python
3) Java
4) C++
5) PHP
#? 5
你選擇了PHP。
select-in 語句常和case-in 語句一起使用。
break
格式如下:
break n
n 表示跳出循環(huán)的層數(shù),如果省略n,則表示跳出當前。
continue
格式如下:
continue n
n 表示循環(huán)的層數(shù):
- 如果省略
n ,則表示continue 只對當前層次的循環(huán)語句有效,遇到continue 會跳過本次循環(huán),忽略本次循環(huán)的剩余代碼,直接進入下一次循環(huán)。
- 如果帶上
n ,比如n 的值為2,那么continue 對內(nèi)層和外層循環(huán)語句都有效,不但內(nèi)層會跳過本次循環(huán),外層也會跳過本次循環(huán),其效果相當于內(nèi)層循環(huán)和外層循環(huán)同時執(zhí)行了不帶n 的continue 。
與break 的區(qū)別:
break 用來結束當前整個循環(huán);
continue 用來結束本次循環(huán),直接跳到下一次循環(huán),如果循環(huán)條件成立,還會繼續(xù)循環(huán);
函數(shù)
函數(shù)的本質(zhì)是一段可以重復使用的腳本代碼,這段代碼被提前編寫好了,放在了指定的位置,使用時直接調(diào)取即可。
函數(shù)定義
格式如下:
function func_name() {
statements
[return value]
}
Tips:關鍵詞function 是可選的,但必須在一個項目中保持一致。
說明:
function 是Shell中的關鍵字,專門用來定義函數(shù),可以不寫,但要求在整個項目腳本中保持一致,即統(tǒng)一不寫或都寫;
func_name 是函數(shù)名,按照約定規(guī)范,函數(shù)名后面必須帶上() ;
statements 是函數(shù)要執(zhí)行的代碼,也就是一組語句;
return value 表示函數(shù)的返回值,其中return 是Shell關鍵字,專門用在函數(shù)中返回一個值;這一部分可以寫也可以不寫。
函數(shù)調(diào)用
調(diào)用Shell函數(shù)時可以給它傳遞參數(shù),也可以不傳遞。如果不傳遞參數(shù),直接給出函數(shù)名字即可,格式如下:
func_name
如果傳遞參數(shù),那么多個參數(shù)之間以空格分隔:
func_name param1 param2 param3...
Tips:不管是哪種調(diào)用方式,函數(shù)名字后面都不需要帶()
函數(shù)參數(shù)
函數(shù)參數(shù)是Shell 位置參數(shù)的一種,在函數(shù)內(nèi)部可以使用$n 來接收,例如,$1 表示第一個參數(shù),$2 表示第二個參數(shù),依次類推。
除了$n ,還有另外三個比較重要的變量:
$# 可以獲取傳遞的參數(shù)的個數(shù);
$@ 或者$* 可以一次性獲取所有的參數(shù)
|