柚子快報(bào)邀請(qǐng)碼778899分享:linux shell函數(shù)
柚子快報(bào)邀請(qǐng)碼778899分享:linux shell函數(shù)
文章目錄
六、函數(shù)和數(shù)組6.1 函數(shù)6.1.1什么是函數(shù)6.1.2 函數(shù)語(yǔ)法6.1.3 函數(shù)的調(diào)用6.1.4 函數(shù)的返回值6.1.5 函數(shù)案例6.1.6 函數(shù)庫(kù)文件6.1.7 遞歸函數(shù)
6.2 數(shù)組6.2.1 定義數(shù)組6.2.2 數(shù)組操作6.2.3 數(shù)組案例
六、函數(shù)和數(shù)組
6.1 函數(shù)
函數(shù)幾乎是學(xué)習(xí)所有的程序設(shè)計(jì)語(yǔ)言時(shí)都必須過(guò)的一關(guān)。對(duì)于學(xué)習(xí)過(guò)其他的程序語(yǔ)言的用戶來(lái)說(shuō),函數(shù)可能并不陌生。但是Shell中的函數(shù)與其他的程序設(shè)計(jì)語(yǔ)言的函數(shù)有許多不同之處。
6.1.1什么是函數(shù)
通俗地講,所謂函數(shù)就是將一組功能相對(duì)獨(dú)立的代碼集中起來(lái),形成一個(gè)代碼塊,這個(gè)代碼可以完成某個(gè)具體的功能。從上面的定義可以看出,Shell中的函數(shù)的概念與其他語(yǔ)言的函數(shù)的概念并沒(méi)有太大的區(qū) 別。從本質(zhì)上講,函數(shù)是一個(gè)函數(shù)名到某個(gè)代碼塊的映射。也就是說(shuō),用戶在定義了函數(shù)之后,就可以通過(guò)函數(shù)名來(lái)調(diào)用其所對(duì)應(yīng)的一組代碼。
使用shell函數(shù)優(yōu)勢(shì) ? 1、把相同的程序段定義為函數(shù),可以減少整個(gè)程序段代碼量,提升開發(fā)效率。 ? 2、增加程序段可讀性、易讀性,提升管理效率。 ? 3、可以實(shí)現(xiàn)程序功能模塊化,使得程序具備通用性(可移植性)。
6.1.2 函數(shù)語(yǔ)法
function 函數(shù)名() {
指令
return
}
簡(jiǎn)化寫法1:
function 函數(shù)名 {
指令
return
}
簡(jiǎn)化寫法2:
函數(shù)名() {
指令
return
}
6.1.3 函數(shù)的調(diào)用
在Shell中,函數(shù)調(diào)用的基本語(yǔ)法如下:
function_name param1 param2 …
在上面的語(yǔ)法中,function_name表示函數(shù)名稱,其后面跟的param1、param2…表示函數(shù)的參數(shù)。
Shell的函數(shù)參數(shù)的語(yǔ)法比較特殊。實(shí)際上,Shell將腳本參數(shù)和函數(shù)參數(shù)做了統(tǒng)一地處理。也就是說(shuō), Shell采用了相同的方法來(lái)處理腳本的參數(shù)和函數(shù)參數(shù)。
(1)調(diào)用函數(shù):直接執(zhí)行函數(shù)名即可。
函數(shù)名
(2)帶參數(shù)的函數(shù)執(zhí)行方法:
函數(shù)名 參數(shù)
與Shell腳本一樣,用戶可以在Shell函數(shù)中使用位置變量來(lái)獲取參數(shù)值。例如,$0表示腳本名稱, $#來(lái) 獲取函數(shù)的參數(shù),$1表示第1個(gè)參數(shù),$2表示第2個(gè)參數(shù)等,依次類推,另外用戶還可以通過(guò)系統(tǒng)變量 $@和 $*獲取所有參數(shù)的值
[root@localhost test6]# vim func.sh
#!/bin/bash
func()
{
echo "the function has $# parameters"
echo "all parameters are $*"
echo "all parameters are $@"
echo "the script's name is $0"
echo "the first parameter is $1"
}
func hello world
[root@localhost test6]# bash func.sh
the function has 2 parameters
all parameters are hello world
all parameters are hello world
the script's name is func.sh
the first parameter is hello
6.1.4 函數(shù)的返回值
首先,用戶可以使用return語(yǔ)句來(lái)返回某個(gè)數(shù)值,這與絕大部分的程序設(shè)計(jì)語(yǔ)言是相同的。但是,在Shell中,return語(yǔ)句只能返回某個(gè)0~255之間的整數(shù)值。
在函數(shù)中,用戶將需要返回的數(shù)據(jù)寫入到標(biāo)準(zhǔn)輸出(stdout),通常這個(gè)操作是使用echo語(yǔ)句來(lái)完成的。然后在調(diào)用程序中將函數(shù)的執(zhí)行結(jié)果賦給一個(gè)變量。這種做法實(shí)際上就是命令替換的一個(gè)變種。
例:
[root@localhost test6]# vim length.sh
#!/bin/bash
length()
{
str=$1
result=0
if [ "$1" != "" ];then
result=${#str}
fi
echo "$result"
}
len=$(length "abcd12")
echo "the string's length is $len"
[root@localhost test6]# bash length.sh
the string's length is 6
6.1.5 函數(shù)案例
示例1:寫一個(gè)腳本,判定192.168.0.200-192.168.0.254之間的主機(jī)哪些在線。 要求: ? 1、使用函數(shù)來(lái)實(shí)現(xiàn)一臺(tái)主機(jī)的判定過(guò)程; ? 2、在主程序中來(lái)調(diào)用此函數(shù)判定指定范圍內(nèi)的所有主機(jī)的在線情況。直接使用函數(shù)實(shí)現(xiàn) 方法一:直接使用函數(shù)實(shí)現(xiàn)(無(wú)參數(shù),無(wú)返回值)
[root@localhost test6]# vim online_host.sh
#!/bin/bash
online() {
for i in {200..254};do
if ping -c 1 192.168.0.$i &>/dev/null
then
echo "192.168.0.$i is up"
else
echo "192.168.0.$i is down"
fi
done
}
online
方法二:使用函數(shù)傳參(有參數(shù),無(wú)返回值)
[root@localhost test6]# vim online_host1.sh
#!/bin/bash
online() {
if ping -c 1 $1 &>/dev/null
then
echo "$1 is up"
else
echo "$1 is down"
fi
}
for i in {200..254}
do
online 192.168.0.$i
done
方法三:使用函數(shù)返回值判斷(有參數(shù),有返回值)
[root@localhost test6]# vim online_host2.sh
#!/bin/bash
online() {
if ping -c 1 $1 >/dev/null
then
return 0
else
return 1
fi
}
for i in {200..254}
do
online 192.168.0.$i
if [ $? -eq 0 ];then
echo "192.168.0.$i is up"
else
echo "192.168.0.$i is down"
fi
Done
示例2:寫一個(gè)腳本,使用函數(shù)完成 ? 1、函數(shù)能夠接受一個(gè)參數(shù),參數(shù)為用戶名; ○ 判斷一個(gè)用戶是否存在 ○ 如果存在,就返回此用戶的shell和UID;并返回正常狀態(tài)值; ○ 如果不存在,就說(shuō)此用戶不存在;并返回錯(cuò)誤狀態(tài)值; ? 2、在主程序中調(diào)用函數(shù);
[root@localhost test6]# vim user_mess.sh
#!/bin/bash
user() {
if id $1 &>/dev/null
then
echo "`grep ^$1 /etc/passwd | cut -d: -f3,7`"
return 0
else
echo "$1 does not exist"
return 1
fi
}
read -p "please input username:" username
until [ "$username" = "quit" -o "$username" = "exit" -o "$username" = "q" ]
do
user $username
if [ $? == 0 ];then
read -p "please input again:" username
else
read -p "no $username,please input again:" username
fi
done
[root@localhost test6]# bash user_mess.sh
please input username:redhat
1000:/bin/bash
please input again:jkl
jkl does not exist
no jkl,please input again:exit
6.1.6 函數(shù)庫(kù)文件
為了方便地重用這些功能,可以創(chuàng)建一些可重用的函數(shù)。這些函數(shù)可以單獨(dú)地放在函數(shù)庫(kù)文件中。 ? 函數(shù)庫(kù)文件定義: 創(chuàng)建一個(gè)函數(shù)庫(kù)文件的過(guò)程非常類似于編寫一個(gè)Shell腳本。腳本與庫(kù)文件之間的唯一區(qū)別在于函數(shù)庫(kù)文件通常只包括函數(shù),而腳本中則可以既包括函數(shù)和變量的定義,又包括可執(zhí)行的代碼。此處所說(shuō)的可執(zhí)行代碼,是指位于函數(shù)外部的代碼,當(dāng)腳本被載入后,這些代碼會(huì)立即被執(zhí)行,毋需另外調(diào)用。 ? 函數(shù)庫(kù)文件的調(diào)用 當(dāng)庫(kù)文件定義好之后,用戶就可以在程序中載入庫(kù)文件,并且調(diào)用其中的函數(shù)。在Shell中,載入庫(kù)文件的命令為.,即一個(gè)圓點(diǎn),其語(yǔ)法如下:
. filename
其中,參數(shù)filename表示庫(kù)文件的名稱,必須是一個(gè)合法的文件名。庫(kù)文件可以使用相對(duì)路徑,也可以使用絕對(duì)路徑。另外,圓點(diǎn)命令和庫(kù)文件名之間有一個(gè)空格。
6.1.7 遞歸函數(shù)
Linux的Shell也支持函數(shù)的遞歸調(diào)用。也就是說(shuō),函數(shù)可以直接或者間接地調(diào)用自身。在函數(shù)的遞歸調(diào)用中,函數(shù)既是調(diào)用者,又是被調(diào)用者。 遞歸函數(shù)的調(diào)用過(guò)程就是反復(fù)地調(diào)用其自身,每調(diào)用一次就進(jìn)入新的一層。 示例:根據(jù)用戶輸入的數(shù)值計(jì)算該數(shù)的階乘
[root@localhost test6]# vim fact.sh
#!/bin/bash
fact()
{
local n="$1"
if [ "$n" -eq 0 ]
then
result=1
else
let "m=n-1"
fact "$m"
let "result=$n * $result"
fi
}
fact "$1"
echo "Factorial of $1 is $result"
[root@localhost test6]# bash fact.sh 0
Factorial of 0 is 1
[root@localhost test6]# bash fact.sh 5
Factorial of 5 is 120
注意:默認(rèn)情況下,除了與函數(shù)參數(shù)關(guān)聯(lián)的特殊變量之外,其他所有的變量都有全局的有效范圍。另外,在函數(shù)內(nèi)部,如果沒(méi)有使用local關(guān)鍵字進(jìn)行修飾,那么函數(shù)中的變量也是全局變量。 例1:函數(shù)的變量是全局變量
[root@localhost test6]# cat global.sh
#!/bin/bash
var="hello world"
func()
{
var="orange"
echo $var
var2="hello"
}
echo "$var"
func
echo "$var"
echo "$var2"
[root@localhost test6]# ./global.sh
hello world
orange
orange
hello
例2:函數(shù)的變量使用local指定為局部變量
[root@localhost test6]# cat 7.sh
#!/bin/bash
var="hello world"
func()
{
local var="orange"
echo "$var"
local var2="hello"
}
echo "$var"
func
echo "$var"
echo "$var2"
[root@localhost test6]# ./7.sh
hello world
orange
hello world
6.2 數(shù)組
所謂數(shù)組,是指將具有相同類型的若干變量按照一定的順序組織起來(lái)的一種數(shù)據(jù)類型。Shell語(yǔ)言對(duì)于數(shù)組的支持非常強(qiáng)大。在Shell中,用戶可以通過(guò)多種方式來(lái)創(chuàng)建一個(gè)數(shù)組。
6.2.1 定義數(shù)組
? 定義數(shù)組
方法一:用小括號(hào)將變量值括起來(lái)賦值給數(shù)組變量,每個(gè)變量之間要用空格進(jìn)行分隔。
array=(value1 value2 value3 ... )
方法二:用小括號(hào)將變量值括起來(lái),同時(shí)采用鍵值對(duì)的形式賦值。當(dāng)通過(guò)鍵值對(duì)定義數(shù)組時(shí),用戶所提供的鍵值對(duì)中的元素索引不一定是連續(xù)的,可以任意指定要賦值的元素的索引。之所以可以這樣操作,是因?yàn)橛脩粢呀?jīng)顯式指定了索引,Shell就可以知道值和索引的對(duì)應(yīng)關(guān)系。
array=([0]=one [1]=two [2]=three ... [n]=valuen)
方法三:分別定義數(shù)組變量的值
array[0]=a;array[1]=b;array[2]=c
方法四:動(dòng)態(tài)的定義變量,并使用命令的輸出結(jié)果作為數(shù)組的內(nèi)容。
array=(命令)
方法五:通過(guò)declare語(yǔ)句定義數(shù)組
declare -a array
? 定義關(guān)聯(lián)數(shù)組:關(guān)聯(lián)數(shù)組使用字符串作為下標(biāo),而不是整數(shù),這樣可以做到見名知意。不同于普通數(shù)組,關(guān)聯(lián)數(shù)組必須使用帶有 -A 選項(xiàng)的 declare 命令創(chuàng)建 方法一:一次賦一個(gè)值
[root@localhost ~]# declare -A array
[root@localhost ~]# array[shuju1]=apple
[root@localhost ~]# array[shuju2]=banana
[root@localhost ~]# echo ${array[*]}
banana apple
方法二:一次賦多個(gè)值
[root@localhost ~]# declare -A a
[root@localhost ~]# a=([index1]=tom [index2]=jack [index3]=alice)
[root@localhost ~]# echo ${a[@]}
tom jack alice
6.2.2 數(shù)組操作
獲取所有元素:
# echo ${array[*]} # *和@ 都是代表所有元素
獲取元素下標(biāo):
# echo ${!array[@]}
# echo ${!array[*]}
獲取數(shù)組長(zhǎng)度:
# echo ${#array[*]}
# echo ${#array[@]}
獲取第一個(gè)元素:
# echo ${array[0]}
添加元素:
# array[3]=d
添加多個(gè)元素:
# array+=(e f g)
以切片方式獲取部分?jǐn)?shù)組元素:(用戶得到的是一個(gè)空格隔開的多個(gè)元素值組成的字符串)
${array[@|*]:start:length}
刪除第一個(gè)元素:
# unset array[0] # 刪除會(huì)保留元素下標(biāo)
刪除數(shù)組:
# unset array
遍歷數(shù)組: ? 方法 1:
#!/bin/bash
IP=(192.168.1.1 192.168.1.2 192.168.1.3)
for ((i=0;i<${#IP[*]};i++)); do
echo ${IP[$i]}
done
# bash test.sh
192.168.1.1
192.168.1.2
192.168.1.3
? 方法 2:
#!/bin/bash
IP=(192.168.1.1 192.168.1.2 192.168.1.3)
for host_ip in ${IP[*]}; do
echo $IP
Done
6.2.3 數(shù)組案例
1、從“標(biāo)準(zhǔn)輸入”讀入n次字符串,每次輸入的字符串保存在數(shù)組array里
[root@localhost test6]# vim str.sh
i=0
n=5
while [ "$i" -lt $n ];do
echo "please input strings...`expr $i + 1`"
read array[$i]
b=${array[$i]}
echo "$b"
i=`expr $i + 1`
done
[root@localhost test6]# bash str.sh
please input strings...1
a
a
please input strings...2
fa
fa
please input strings...3
fa
fa
please input strings...4
few
few
please input strings...5
wwwwwwwef
wwwwwwwef
2、將字符串里的字母逐個(gè)放入數(shù)組,并輸出到“標(biāo)準(zhǔn)輸出”
[root@localhost test6]# vim letter.sh
chars='ajfkalfjoiweqqef'
for ((i=0;i<${#chars};i++));do
array[$i]=${chars:$i:1}
echo ${array[$i]}
done
說(shuō)明:KaTeX parse error: Expected '}', got 'EOF' at end of input: {chars:i:1},表示從chars字符串的 $i 位置開始,獲取 1 個(gè)字符
3、把1-3這3個(gè)數(shù)字存到數(shù)組里,分別乘以8然后依次輸出。
[root@localhost test6]# vim number.sh
#!/bin/bash
array=(`seq 3`)
for ((i=0;i<${#array[@]};i++))
do
echo $[${array[$i]}*8]
echo $((${array[$i]}*8))
result=let "$array[$i] * 8"
echo $result
echo `expr ${array[$i]} * 8`
done
[root@localhost test6]# bash number.sh
8
16
24
4、打印下面這句話中字母數(shù)不大于6的單詞:
? cat is favorite to eat fish
[root@localhost test6]# vim word.sh
#!/bin/bash
array=(cat is favorite to eat fish)
for i in ${array[*]}
do
if [ ${#i} -lt 6 ]
then
echo $i
fi
done
[root@localhost test6]# bash word.sh
cat
is
to
eat
fish
練習(xí): 1、編寫函數(shù),實(shí)現(xiàn)打印綠色OK和紅色FAILED 判斷是否有參數(shù),存在為Ok,不存在為FAILED 2、編寫函數(shù),實(shí)現(xiàn)判斷是否無(wú)位置參數(shù),如無(wú)參數(shù),提示錯(cuò)誤 3、編寫函數(shù)實(shí)現(xiàn)兩個(gè)數(shù)字做為參數(shù),返回最大值 4、編寫函數(shù),實(shí)現(xiàn)兩個(gè)整數(shù)位參數(shù),計(jì)算加減乘除。 5、將/etc/shadow文件的每一行作為元素賦值給數(shù)組 6、使用關(guān)聯(lián)數(shù)組統(tǒng)計(jì)文件/etc/passwd中用戶使用的不同類型shell的數(shù)量 7、使用關(guān)聯(lián)數(shù)組按擴(kuò)展名統(tǒng)計(jì)指定目錄中文件的數(shù)量
柚子快報(bào)邀請(qǐng)碼778899分享:linux shell函數(shù)
文章來(lái)源
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。