shell腳本 函數 函數介紹 定義函數 函數使用 互動式環境下定義和使用函數 腳本中定義和使用函數 函數在使用前須先被定義,所以在腳本中使用函數是,必須在腳本開始前定義函數。 調用函數僅使用其函數名即可 示例: cat func1 !/bin/bash func1 hello() { echo " ...
shell腳本-函數
函數介紹
函數function是由若幹條shell命令組成的語句塊,實現代碼重用和模塊化編程。
它與shell程式形式上是相似的,不同的是它不是一個單獨的進程,不能獨立運行,而是shell 程式的一部分。
函數和shell程式比較相似,區別在於:
Shell 程式在子Shell中運行
而Shell函數在當前Shell中運行。因此在當前Shell中,函數可以對shell 中變數進行修改
定義函數
函數由兩部分組成,函數名和函數體。
/etc/init.d/functions中提供了些系統設定好的函數,可以直接調用。
help function
function name { COMMANDS ; }
or
name () { COMMANDS ; }
語法一:
function f_name {
... 函數體...
}
語法二:
function f_name() {
... 函數體...
}
語法三:
f_name() {
... 函數體...
}
定義方式:
可在互動式環境下定義函數
可在腳本中定義函數
函數使用
可將函數放在腳本文件中使用
可放在只包含函數的單獨文件中使用
可在互動式環境中使用
函數調用:
函數只有被調用才會執行
調用給定函數名,函數名出現的地方,會被自動替換為函數代碼
函數的生命周期
被調用時創建,返回時終止
互動式環境下定義和使用函數
示例:在命令行中直接進行
dir() {
> ls -l
> }
定義該函數後,使用$dir,其顯示結果同ls -l的作用相同
該dir函數將會一直保留到用戶從其他退出,或者執行unset dir命令。
腳本中定義和使用函數
函數在使用前須先被定義,所以在腳本中使用函數是,必須在腳本開始前定義函數。
調用函數僅使用其函數名即可
示例:
cat func1
#!/bin/bash
# func1
hello() {
echo "Hello there today's date is `date +%F`"
}
echo "now going to the function hello"
hello
echo "back from the function"
函數返回值
函數有兩種返回值,分別為執行結果的返回值和退出狀態碼。
函數的執行結果返回值:
使用echo 等命令進行輸出
函數體中調用命令的輸出結果
函數的退出狀態碼:
預設取決於函數中執行的最後一條命令的退出狀態碼
自定義退出狀態碼,其格式為:
return 從函數中返回,用最後狀態命令決定返回值
return 0 無錯誤返回。
return 1-255 有錯誤返回
函數文件
可以將經常使用的函數存入函數文件,然後將函數文件載入shell。
文件名可任意選取,但最好與相關任務有某種聯繫,如functions.main
一旦函數文件載入shell ,就可以在命令行或腳本中調用函數。
可以使用set或declar -f 命令查看所有定義的函數,其輸出列表包括已經載入shell 的所有函數。
創建函數文件
函數文件示例:
cat functions.main
#!/bin/bash
#functions.main
findit()
{
if [ $# -lt 1 ] ; then
echo "Usage:findit file"
return 1
fi
find / -name $1 –print
}
函數中使用return 來返回值,exit用於腳本
載入函數
函數文件已創建好後,要將它載入shell.
定位函數文件並載入shell的格式:
. | source filename
註意:此即< 點> < 空格> < 文件名>,這裡的文件名要帶正確路徑.
示例:
.|source functions.main
載入函數稱為環境函數
子進程也可使用
使用export -f function_name來載入成為環境函數
檢查查看載入的函數
使用set 或者 declar -f 命令檢查函數是否已載入。
執行shell函數
要執行函數,簡單地鍵入函數名即可。
改動shell函數
若要改動函數,首先用unset 命令從shell 中刪除函數,改動完畢後,再重新載入此文件。
刪除shell函數
使用unset 命令完成刪除函數。
unset function_name
函數參數
函數可接收參數。
傳遞參數給函數:
調用函數時,在函數名後面以空白分隔給定參數列表即可。
如“testfunc arg1 arg2 ...”
在函數體中當中,可使用$1, $2, ...調用參數,還可以使用$@, $*, $# 等特殊變數。
函數變數
變數作用域:
環境變數:當前shell和子shell有效
本地變數:只在當前shell進程有效,執行腳本會啟動專用子shell 進程。因此,本地變數的作用範圍是當前shell 腳本程式文件,包括腳本中的函數。
局部變數:函數結束時變數被自動銷毀
註意:
如果函數中有局部變數,如果其名稱同本地變數,使用局部變數。
在函數中定義局部變數的方法
local NAME=VALUE
declare -I NAME=VALUE
定義全局變數
declare -ig NAME=VALUE
函數遞歸
函數可以直接或間接地調用自身。
在函數的遞歸調用中,函數既是調用者,又是被調用者。
遞歸函數的調用過程就是反覆地調用其自身,每調用一次就進入新的一層。
從基礎層開始來計算,註意遞歸的層數。
遞歸示例:
階乘
階乘是數學術語一個正整數的階乘(factorial)是所有小於及等於該數的正整數的積,並且有0 的階乘為1 ,自然數n 的階乘寫作n!
n!=1 ×2 ×3 ×... ×n
階乘亦可以遞歸方式定義:
0!=1
n!=n(n-1)(n-2)...1
n(n-1)! = n(n-1)(n-2)!
腳本示例:cat fact.sh
#!/bin/bash
#
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])] or echo $[$1*`fact $[$1-1]`]
fi
}
fact $1
fork炸彈
fork 炸彈是一種惡意程式,它的內部是一個不斷在fork 進程的無限迴圈,實質是一個簡單的遞歸程式。
由於程式是遞歸的,如果沒有任何限制,這會導致這個簡單的程式迅速耗盡系統裡面的所有資源
函數實現
:(){ :|:& };:
bomb() { bomb | bomb & }; bomb
腳本實現
cat Bomb.sh
#!/bin/bash
./$0|./$0&