一、Shell函數
1、函數的用法
Shell函數可用于存放一系列的指令。在Shell腳本執行的過程中,函數被置于內存中,每次調用函數時不需要從硬盤讀取,因此運行的速度比較快。在Shell編程中函數并非是必須的元素,但使用函數可以對程序進行更好的組織。將一些相對獨立的代碼變成函數,可以提高程序可讀性與重用性,避免編寫大量重復代碼
格式:
function() {代碼塊
[return x]}function
function | 關鍵字表示定義一個函數,可以省略 |
{ | 表示函數執行命令的入口,該符號可以與函數名同行也可以在函數名下一行的句首 |
} | 符號表示函數體結束,兩個大括號之間{}是函數體 |
代碼塊 | 可以是任意的 Shell 命令,也可以調用其他函數 |
return | 表示退出函數返回一個退出值,通過返回值判斷執行是否成功,也可以使用 exit 終止整個 Shell 腳本 |
Shel1 函數調用的方法為:函數名「參數 1]〔參數 2]
栗子1:兩個數求和
#!/bin/bash
#定義 sum 函數
sum() {
read -p "請輸入第一個數字:" A
#檢查是否為有效數字
if ! [[ $A =~ ^[0-9]+$ ]]
thenecho "這不是一個有效數字,請重新輸入"return 1
firead -p "請輸入第二個數字:" B
if ! [[ $B =~ ^[0-9]+$ ]]
thenecho "這不是一個有效數字,請重新輸入"return 1
fi#計算兩數之和
result=$((A + B))
echo "兩數之和是:$result"
}
#調用函數
sum
執行結果:
栗子2:監控系統資源
該函數會定期監控系統的 CPU 和內存使用率,當使用率超過設定的值時,會發送報警信息,這里簡單模擬為輸出到控制臺,實際應用中可擴展為發送郵件、短信等。
#!/bin/bash
send_alert() {local message=$1
echo "ALERT:$message"}#系統資源控制函數
monitor_system_resources() {local cpu_threshold=$1
local mem_threshold=$1
local interval=$3while true
do
#獲取CPU的使用率
cpu_usage=$(top -bn1 | grep Cpu | awk '{print $2+$4}')
#獲取內存使用率
mem_usage=$(free | grep Mem | awk '{print $3/$2 *100}')if (($(echo "$cpu_usage > $cpu_threshold" |bc -l)))
thensend_alert "CUP usage (${cpu_usage}%)"
fiif (($(echo "$mem_usage > $mem_threshold" |bc -l)))
thensend_alert "Mem usage (${mem_usage}%)"
fisleep "$interval"done
}
#調用函數
monitor_system_resources 2 5 2
執行結果:
參數說明:函數接收三個參數,分別是CPU使用率值、內存使用率值以及監控間隔時間(秒)
循環監控:使用 while true 循環不斷監控系統資源。通過 top 和 free 命令獲取 CPU 和內存使用率,使用 bc 命令進行浮點數比較。
報警處理:當使用率超過閾值時,調用 send alert 函數發送報警信息
2、函數變量的作用范圍
在 Shel1 腳本中函數的執行并不會開啟一個新的子 Shell,而是僅在當前定義的 shel1 環境中有效。如果 Shel1 腳本中的變量沒有經過特殊設定,默認在整個腳本中都是有效的。
在編寫腳本時,有時需要將變量的值限定在函數內部,可以通過內置命令 1ocal 來實現。函數內部變量的使用,可以避免函數內外同時出現同名變量對腳本結果的影響。local 命令的使用如下所示。
#!/bin/bash
AAA(){
local i
i=8
echo $i
}
i=9
AAA
echo $i
上述腳本中,AAA?函數內部使用了 local 命令設置變量 i,其作用是將變量 i 限定在函數內部AAA?函數外部同樣定義了變量 ,內部變量 i 和全局變量 i 互不影響。腳本執行時先調用了函數AAA,函數內部變量 i 為 8,所以輸出結果是 8。調用完函數之后,給變量i 賦值為 9,再打印外部變量 i,所以又輸出 9
3、遞歸函數
Shell 也可以實現遞歸函數,就是可以調用自己本身的函數。在 Linux 系統上編寫shell腳本的時候,經常需要遞歸遍歷系統的目錄,列出目錄下的文件和目錄,逐層遞歸列出,并對這些層級關系進行展示。具體的實現過程如下所示
#!/bin/bash
#定義遞歸遍歷目錄的函數
traverse_directory() {
local dir=$1
#遍歷當前目錄下所有的目錄和文件
for item in "$dir"/*
do if [ -d "$item" ]then
#如果是目錄則遞歸調用函數繼續循環echo "這是目錄:$item"traverse_directory "$item"elif [ -f "$item" ]then
#如果是文件就輸出路徑echo "這是文件:$item"fi
done
}
#調用函數
#“.”:當前目錄
traverse_directory "."
執行結果:
二、Shell數組
在 shell 腳本中,數組是一種常見的數據結構,主要的應用場景包括:獲取數組長度、獲取元素長度、遍歷元素、元素切片、元素替換、元素刪除等等。shell中的數組與 Java、c、Python 不同,只有一維數組,沒有二維數組。數組元素的大小與限制,也不需要事先定義。Shell 數組用括號()來表示,元素用空格分隔,元素的下標與大部分編程語言類似從開始。
fruits=("Apple" "Banana" "Cherry") # 元素帶空格時必須加引號
nums=(10 20 30) # 數字類型可不加引號
1、獲取數組長度
在 shell 編程中,數組是一種用于存儲多個值的數據結構。獲取數組長度(即數組中元素的個數)在很多場景下都非常有用,比如進行數組遍歷、數據處理等。普通數組是 Shell 中最常見的數組類型,其下標是從0 開始的連續整數。獲取普通數組長度可以使用 ${#數組名[@]}或 ${#數組名[*]} 這兩種語法,它們的效果是一樣的。
#定義一個數組A
A=(1 2 3 4 5 6)#打印數組A的長度
#方法一:
echo ${#A[@]}
#方法二:
echo ${#A[*]}
2、讀取指定元素對應的值
在 shell?編程里,你可以讀取數組中指定下標的元素,也可以給指定下標的數組元素賦值。普通數組是 Shell?中最常用的數組類型,其下標是從0開始的整數
#定義一個數組A
A=(1 2 3 4 5 6)#讀取3號元素對應的值
echo ${A[3]}#讀取數組中所有的元素值
echo ${A[@]
echo ${A[*]
3、數組遍歷
在 Shell 編程里,數組遍歷指的是按順序訪問數組中的每一個元素,并對這些元素執行特定操作的過程,這在處理一組相關數據時非常有用,比如批量處理文件、統計數據等
#!/bin/bash
A=("好" "好" "學" "習" "天" "天" "向" "上")
for i in ${A[@]}
do echo $i
done
執行結果:
4、數組切片
數組切片是一種操作,用于從數組中提取出一部分連續的元素,形成一個新的數組。這個操作在很多編程語言中都有支持,不過不同語言實現數組切片的語法和方式會有所差異。在Bash腳本里,也可以進行數組切片操作,語法是${array[@]:start:length},其中start是開始的索引,length是要提取的元素個數
#定義一個數組A
A=(1 2 3 4 5 6)echo ${A[@]}echo ${A[@]:0:5}echo ${A[@]:1:5}
5、數組替換
#定義一個數組A
A=(1 2 3 4 5 6)#打印數組元素對應的值
echo ${A[@]}
#1 2 3 4 5 6#將4號元素對應的值5修改為100
echo ${A[@]/5/100}#將4號元素對應的值6修改為200
echo ${A[@]/6/200}
6、數組刪除
#定義一個數組A
A=(1 2 3 4 5 6)#刪除數組中的指定的3號元素
unset A[3]#刪除數組
unset ${A[*]}
unset A
三、Shell腳本調試
在Shell腳本開發中,經常碰到一些規范方面的問題,例如忘了使用引號或在if語句末尾處忘記加fi結束。要注意把復雜的腳本簡單化,要思路清晰,并且分段實現。當執行腳本時出現錯誤后,不要只看那些提示的錯誤行,而是要觀察整個相關的代碼段。
為避免編寫的腳本出錯,除了在編寫腳本時注意書寫規范,排除語法錯誤,更重要的是利用調試腳本工具來調試腳本。echo命令是最有用的調試腳本工具之一,一般在可能出現問題的腳本中加入echo命令,采用的是分段排查的方式
除了echo命令之外,bash Shell也有相應參數可以調試腳本
sh [-nvx] 腳本名
-n | 不會執行該腳本,僅查詢腳本語法是否有問題,如果沒有語法問題就不顯示任何內容,如果有問題會提示報錯 |
-v | 在執行腳本時,先將腳本的內容輸出到屏幕上然后執行腳本,如果有錯誤,也會給出錯誤提示 |
-x | 將執行的腳本內容輸出到屏幕上,這個是對調試很有用的參數 |
#!/bin/bash
set -x #開啟調試
#定義 sum 函數
sum() {
read -p "請輸入第一個數字:" A
#檢查是否為有效數字
if ! [[ $A =~ ^[0-9]+$ ]]
thenecho "這不是一個有效數字,請重新輸入"return 1
firead -p "請輸入第二個數字:" B
if ! [[ $B =~ ^[0-9]+$ ]]
thenecho "這不是一個有效數字,請重新輸入"return 1
fi
set +x #關閉調試
#計算兩數之和
result=$((A + B))
echo "兩數之和是:$result"
}
#調用函數
sum
總結:
函數:函數是Shell腳本中組織代碼、提高復用性的重要手段。通過將一系列指令封裝成函數,可以避免代碼重復,使腳本更加簡潔易讀。函數的定義與調用簡單直觀,支持參數傳遞和遞歸調用,為模塊化開發提供了便利。
數組:作為Shell腳本中的一種重要數據結構,數組支持存儲多個值,并提供了豐富的操作方法,如獲取數組長度、讀取和賦值、遍歷、切片、替換和刪除元素等。這些功能在處理一組相關數據時非常有用。
調試與測試:在Shell腳本編寫過程中,調試與測試是確保腳本正確運行的關鍵環節。通過使用echo命令和bash的調試參數(-n、-v、-x),可以方便地定位和解決問題,提高腳本的穩健性