- ver: 1.0
- 博客:https://www.cnblogs.com/Rohn
- 本文介紹了Shell經常使用的結構化語句。
數組(Array)是若干數據的集合,其中的每一份數據都稱爲元素(Element)。git
Bash只支持一維數組(不支持多維數組),初始化時不須要定義數組大小,理論上能夠存放無限量的數據。正則表達式
與大部分編程語言相似,數組元素的下標由0開始。express
Shell數組用括號來表示,元素用"空格"符號分割開。格式以下:編程
array_name=(ele1 ele2 ele3 ... elen)
Tips:賦值號
=
兩邊不能有空格,必須緊挨着數組名和數組元素。數組
獲取數組中的元素要使用下標[]
,下標能夠是一個整數,也能夠是一個結果爲整數的表達式;固然,下標必須大於等於0。格式以下:bash
${array_name[index]}
Tips:
array_name
是數組名,index
是下標。編程語言
Shell是弱類型的,它並不要求全部數組元素的類型必須相同,例如:函數
arr=(10 24 'ddd' 'ab22' 5)
使用@
或*
能夠獲取數組中的全部元素,格式以下:學習
${array_name[*]} ${array_name[@]}
使用#
來獲取數組元素的個數,格式以下:測試
${#array_name[@]} ${#array_name[*]}
數組合並,就是將兩個或兩個以上的數組合併成一個個數組,格式以下:
array_new=(${array1[@]} ${array2[@]}...${arrayn[@]}) array_new=(${array1[*]} ${array2[*]}...${arrayn[*]})
使用unset
關鍵字來刪除數組元素,格式以下:
unset array_name[index]
若是不寫下標,則表明刪除整個數組全部元素,格式以下:
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
語句,它們都根據命令的退出狀態來判斷條件是否成立。
基本結構格式:
if condition; then statement(s) fi
condition
是判斷條件,若是condition
成立(返回True),那麼then
後邊的語句將會被執行;若是 condition不成立(返回False),那麼不會執行任何語句。
Tips:最後必須以
fi
來閉合,fi
就是if
倒過來拼寫。
若是有兩個分支,就可使用if-else
語句,格式:
if condition; then statement1 else statement2 fi
若是condition
成立,那麼then
後邊的 statement1
語句將會被執行;不然,執行else
後邊的statement2
語句。
當分支比較多時,可使用if-elif-else
結構,格式:
if condition1; then statement1 elif condition2;then statement2 ... else statementn fi
Tips:
if
和elif
後邊都得跟着then
。
語句的執行邏輯:
condition1
成立,那麼執行statement1
,若是不成立,則執行elif
語句;elif
語句不成立,則執行else
語句;當分支較多,且判斷條件比較簡單時,推薦使用case-in
語句。格式以下:
case expression in pattern1) statement1 ;; pattern2) statement2 ;; ... *) statementn esac
expression
表示表達式,既能夠是一個變量、一個數字、一個字符串,還能夠是一個數學計算表達式,或者是命令的執行結果,只要可以獲得expression
的值就能夠。pattern
表示匹配模式,能夠是一個數字、一個字符串,甚至是一個簡單的正則表達式。case
會將expression
的值與 pattern1
、pattern2
...patternn
逐個進行匹配:
expression
和某個模式(好比 pattern2)匹配成功,就會執行這模式(好比 pattern2)後面對應的全部語句(該語句能夠有一條,也能夠有多條),直到碰見雙分號;;
才中止;而後整個case-in
語句就執行完了,程序會跳出整個 case-in
語句,執行esac
後面的其它語句。*)
後面的語句(*
表示其它全部值),直到碰見雙分號;;
或者esac
才結束。*)
至關於多個if
分支語句中最後的else
部分。Tips:分支
*)
並非什麼語法規定,它只是一個正則表達式,*
表示任意字符串,因此無論expression
的值是什麼,*)
總能匹配成功。所以,能夠沒有*)
部分,若是expression
沒有匹配到任何一個模式,那麼就不執行任何操做。
除最後一個分支外(這個分支能夠是普通分支,也能夠是*)
分支),其它的每一個分支都必須以;;
結尾,;;
表明一個分支的結束,不寫的話會有語法錯誤。最後一個分支能夠寫;;
,也能夠不寫,由於不管如何,執行到esac
都會結束整個case-in
語句。
case-in
的pattern
部分支持簡單的正則表達式,具體來講,可使用如下幾種格式:
格式 | 說明 |
---|---|
* |
表示任意字符串。 |
[abc] | 表示 a、b、c 三個字符中的任意一個。好比,[15ZH] 表示 一、五、Z、H 四個字符中的任意一個。 |
[m-n] | 表示從 m 到 n 的任意一個字符。好比,[0-9] 表示任意一個數字,[0-9a-zA-Z] 表示字母或數字。 |
| |
表示多重選擇,相似邏輯運算中的或運算。好比,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.
循環結構語句大體分爲4種:
當條件知足時,while
重複地執行一組語句,當條件不知足時,就退出while
循環。格式以下:
while condition; do statements done
執行流程以下:
condition
進行判斷,若是該條件成立,就進入循環,執while
循環體中的語句,也就是do
和done
之間的語句。這樣就完成了一次循環。done
的時候都會從新判斷condition
是否成立,若是成立,就進入下一次循環,繼續執行do
和done
之間的語句,若是不成立,就結束整個while
循環,執行done
後面的其它Shell
代碼。condition
就不成立,那麼程序就不會進入循環體。格式一:
while true; do statements done
格式二:
while [ 1 ]; do statements done
until
循環當判斷條件不成立時才進行循環,一旦判斷條件成立,就終止循環。
until condition; do statements done
until
循環的執行流程爲:
condition
進行判斷,若是該條件不成立,就進入循環,執行until
循環體中的語句(do
和done
之間的語句),這樣就完成了一次循環。done
的時候都會從新判斷condition
是否成立,若是不成立,就進入下一次循環,繼續執行循環體中的語句,若是成立,就結束整個 until
循環,執行done
後面的其它Shell
代碼。格式以下:
for((exp1; exp2; exp3)); do statements done
exp1
、exp2
、exp3
是三個表達式,其中exp2
是判斷條件,for
循環根據exp2
的結果來決定是否繼續下一次循環;
它的運行過程爲:
exp1
。exp2
,若是它的判斷結果是成立的,則執行循環體中的語句,不然結束整個for
循環。exp3
。exp2
的判斷結果不成立,就結束循環。格式以下:
for variable in value_list; do statements done
variable
表示變量,value_list
表示取值列表。
每次循環都會從value_list
中取出一個值賦給變量 variable
,而後進入循環體(do
和done
之間的部分),執行循環體中的statements
。直到取完value_list
中的全部值,循環就結束了。
value_list
:
for i in 1 2 3 'dd';do echo $i;done
{start..end}
,例如:# 求1到10的和 sum=0 for i in {1..10}; do sum=$((sum+i)) done echo $sum
# 求100之內偶數的和 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
循環用來加強交互性,它能夠顯示出帶編號的菜單,用戶輸入不一樣的編號就能夠選擇不一樣的菜單,並執行不一樣的功能,很是適合終端(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
是死循環,輸入空值或者輸入的值無效,都不會結束循環,只有遇到break
語句,或者按下Ctrl+D
組合鍵才能結束循環。
例如:
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 n
n
表示跳出循環的層數,若是省略n,則表示跳出當前。
格式以下:
continue n
n
表示循環的層數:
n
,則表示continue
只對當前層次的循環語句有效,遇到continue
會跳過本次循環,忽略本次循環的剩餘代碼,直接進入下一次循環。n
,好比n
的值爲2,那麼continue
對內層和外層循環語句都有效,不但內層會跳過本次循環,外層也會跳過本次循環,其效果至關於內層循環和外層循環同時執行了不帶n
的continue
。與break
的區別:
break
用來結束當前整個循環;continue
用來結束本次循環,直接跳到下一次循環,若是循環條件成立,還會繼續循環;函數的本質是一段能夠重複使用的腳本代碼,這段代碼被提早編寫好了,放在了指定的位置,使用時直接調取便可。
格式以下:
function func_name() { statements [return value] }
Tips:關鍵詞
function
是可選的,但必須在一個項目中保持一致。
說明:
function
是Shell中的關鍵字,專門用來定義函數,能夠不寫,但要求在整個項目腳本中保持一致,即統一不寫或都寫;func_name
是函數名,按照約定規範,函數名後面必須帶上()
;statements
是函數要執行的代碼,也就是一組語句;return value
表示函數的返回值,其中return
是Shell關鍵字,專門用在函數中返回一個值;這一部分能夠寫也能夠不寫。調用Shell函數時能夠給它傳遞參數,也能夠不傳遞。若是不傳遞參數,直接給出函數名字便可,格式以下:
func_name
若是傳遞參數,那麼多個參數之間以空格分隔:
func_name param1 param2 param3...
Tips:不論是哪一種調用方式,函數名字後面都不須要帶
()
函數參數是Shell
位置參數的一種,在函數內部可使用$n
來接收,例如,$1
表示第一個參數,$2
表示第二個參數,依次類推。
除了$n
,還有另外三個比較重要的變量:
$#
能夠獲取傳遞的參數的個數;$@
或者$*
能夠一次性獲取全部的參數