shell函數和數組

[toc]shell

shell函數和數組

1、shell中的函數

1.1 函數格式1

function name {
    commands
}

示例1:vim

#! /bin/bash

function inp(){             //定義一個inp的函數

echo $1 $2 $3 $0 $#         

}

inp 1 a 2 b                 //傳入參數             //傳入參數

運行結果數組

[root@xavi ~]# sh function1.sh
1 a 2 function1.sh 4
  • [ ] $1 : 第一個參數 就是如上的「2」
  • [ ] $2 : 第二個參數 就是如上的「b」
  • [ ] $3 : 第三個參數 就是如上的「3」
  • [ ] $0 : 腳本的自己名稱 如上的「function1.sh」
  • [ ] $# : 其實就是統計有幾個參數這邊是「2 b 3 c」 那就是$# = 4
  • [ ] $@ : 表明全部的參數 2 b 3 c

1.2 函數格式2

neme() {
    commands
}
  • 示例1
#!/bin/bash

sum() {             //定義的函數名爲sum
    s=$[$1+$2]
    echo $s
}
sum 1 2

運行bash

[root@xavi ~]# sh function2.sh
3
  • 示例2

任務:輸入網卡的名字,檢查網卡的IP地址:

先從普通命令調試開始:ide

mark

最終肯定了有效命令爲:函數

ifconfig |grep -A1 "ens33: " |awk '/inet/ {print $2}'

函數:oop

#!/bin/bash
ip()
{
  ifconfig |grep -A1 "$1: " |awk '/inet/ {print $2}'
}

read -p "please input the eth name: "eth
ip $eth

運行結果:this

[root@xavi ~]# sh funciton3.sh
please input the eth name: eth33
192.168.72.130
192.168.72.150
127.0.0.1
192.168.122.1

修改完整:命令行

vim funciton3.sh

#!/bin/bash
ip()
{
  ifconfig |grep -A1 "$eth " |awk '/inet/ {print $2}'
}

read -p "please input the eth name: " eth
UseIp=`ip $eth`
echo "$eth adress is $UseIp"

運行結果:調試

[root@xavi ~]# sh funciton3.sh
please input the eth name: ens33: 
ens33: adress is 192.168.72.130
[root@xavi ~]# sh funciton3.sh
please input the eth name: ens33:0:
ens33:0: adress is 192.168.72.150

2.擴展函數定義:

使用函數

#!/bin/bash
# using a function in a script

function func1 {
   echo " This is an example of a function"
}

count=1
while [ $count -le 5 ]
do
  func1
  count=$[$count + 1 ]
done 

echo "this is the end of the loop"
func1
echo "Now this is the end of the srcipt"

運行結果

[root@xavi ~]# sh fun1.sh
 This is an example of a function
 This is an example of a function
 This is an example of a function
 This is an example of a function
 This is an example of a function
this is the end of the loop
 This is an example of a function
Now this is the end of the srcipt

* 示例:

[root@xavi ~]# vim fun2.sh

#!/bin/bash
# using a function located in the middile of a script

count=1
echo "This line comes before the function definition"

function func1 {
   echo " This is an example of a function"
}

while [ $count -le 5 ]
do
  func1
  count=$[$count + 1 ]
done 

echo "this is the end of the loop"
func2
echo "Now this is the end of the srcipt"

function func2 {
   echo "This is an example of a function"
}

[root@xavi ~]# sh fun2.sh
This line comes before the function definition
 This is an example of a function
 This is an example of a function
 This is an example of a function
 This is an example of a function
 This is an example of a function
this is the end of the loop
fun2.sh:行19: func2: 未找到命令
Now this is the end of the srcipt

第一個函數func1在腳本中是在幾條語句以後才定義的,在被引用時shell能夠找到它,可是func2是在被定義前被引用,產生了錯誤.

函數名是惟一的,不然也會有問題,若重複定義,會引用第二個定義

3. 函數返回值問題

3.1 默認退出狀態碼,使用標準的$?變量來 決定函數的退出狀態碼

[root@xavi ~]# vim func4.sh

#!/bin/bash
# testing the exit status of a fuction

func1() {
  echo "trying to display a non-existent file"
  ls -l badfile

}

echo "testing the function:"
func1
echo "the exit status is: $?"

運行結果

[root@xavi ~]# sh func4.sh
testing the function:
trying to display a non-existent file
ls: 沒法訪問badfile: 沒有那個文件或目錄
the exit status is: 2

函數退回的狀態碼是2,由於函數左後一條命令沒有成功運行,可是沒法知道函數中的其餘命令是否成功運行,看下例:

#!/bin/bash
# testing the exit status of a fuction

func1() {
   ls -l badfile
  echo "This was a test of a bad command"

}

echo "testing the function:"
func1
echo "the exit status is: $?"

運行結果

[root@xavi ~]# sh func5.sh
testing the function:
ls: 沒法訪問badfile: 沒有那個文件或目錄
This was a test of a bad command
the exit status is: 0

因爲函數一成功運行的echo語句結尾,退出狀態碼就是0,儘管函數中有一天命令沒有成功運行,使用函數的默認退出狀態碼是很危險的,幸運的是,有幾種辦法能夠解決這個問題

3.2 使用return命令

使用return命令來退出函數並返回特定的退出狀態碼。

[root@xavi ~]# vim return.sh

#!/bin/bash
# using the return command in a function

 function db1 {
    read -p "Enter a value: " value
    echo "doubling the value"
    return $[ $value*2 ]
 }

db1
echo "The new value is $?"

運行後

[root@xavi ~]# sh return.sh
Enter a value: 33
doubling the value
The new value is 66
[root@xavi ~]# sh return.sh
Enter a value: 200
doubling the value
The new value is 144  //退出的狀態碼必須在0~255之間,200*2-256=144

3.3 使用函數輸出

將函數的輸出保存到shell變量中

#!/bin/bash
# using the echo to return a value

function db1{
  read -p "Enter a value: " value
  echo $[ $value*2 ]
}

result=`db1`
echo "The new value is $result"
[root@xavi ~]# sh result.sh
Enter a value:200
The new value is 400

4.1 在函數中使用變量

a. 向函數傳遞參數,函數名會在$0變量中定義,函數命令行尚德任何參數都會經過$一、$2等定義,也能夠用特殊變量$#來判斷傳給函數的參數數目(個數)。

在腳本中指定函數時,必須將參數和函數放在同一行,像這樣
func1 $value1 10
而後函數能夠用參數 環境變量來得到參數值,舉例:

[root@xavi ~]# vim function6.sh

#!/bin/bash
# passing parameters to a fucntion

function addem {
     if [ $# -eq 0 ] || [ $# -gt 2 ]
     then
        echo -1
    elif [ $# -eq 1 ]
    then
        echo $[ $1 + $1 ]
    else
        echo $[ $1 + $2 ]
    fi
}

echo -n "Adding 10 and 15: "
value=`addem 10 15`
echo $value

echo -n "Let's try adding just one number: "
value=`addem 10`
echo $value

echo -n "Now trying adding no numbers: "
value=`addem`
echo $value

echo -n "Finally, try adding three numbers: "
value=`addem 10 15 20`
echo $value

運行結果

[root@xavi ~]# sh function6.sh
Adding 10 and 15: 25
Let's try adding just one number: 20
Now trying adding no numbers: -1
Finally, try adding three numbers: -1

腳本中的addem函數首先會檢查腳本傳給它的參數數目,若是沒有任何參數,或者多於兩個參數,addem會返回值-1.若是隻有一個或者兩個參數,addem會將他們加起來生成結果.

b.在函數中處理變量,全局變量和局部變量

1. 全局變量

全局變量是在shell腳本中任何地方都有效的變量。若是你在腳本的主體部分定義了一個全局
變量,那麼能夠在函數內讀取它的值。相似地,若是你在函數內定義了一個全局變量,能夠在腳
本的主體部分讀取它的值。
默認狀況下,你在腳本中定義的任何變量都是全局變量。在函數外定義的變量可在函數內正
常訪問。

[root@xavi ~]# vim func8.sh

#!/bin/bash
# using a global variable to pass a value

function db1 {
value=$[ $value *2 ]
}

read -p "Enter a value: " value
db1
echo "The new value is : $value"

[root@xavi ~]# sh func8.sh
Enter a value: 450
The new value is : 900

$value變量在函數外定義並被賦值。當dbl函數被調用時,該變量及其值在函數中都依然有
效。若是變量在函數內被賦予了新值,那麼在腳本中引用該變量時,新值也依然有效。
但這其實很危險,尤爲是若是你想在不一樣的shell腳本中使用函數的話。它要求你清清楚楚地
知道函數中具體使用了哪些變量,包括那些用來計算非返回值的變量。這裏有個例子可說明事情
是如何搞砸的。

#!/bin/bash
# demonstrating a bad use of variables
function func1 {
temp=$[ $value + 5 ]
result=$[ $temp * 2 ]
}
temp=4
value=6
func1
echo "The result is $result"
if [ $temp -gt $value ]
then
echo "temp is larger"
else
echo "temp is smaller"
fi
運行結果
[root@xavi ~]# sh badtest1.sh
The result is 22
temp is larger

因爲函數中用到了$temp變量,它的值在腳本中使用時受到了影響,產生了意想不到的後果。
有個簡單的辦法能夠在函數中解決這個問題,下節將會介紹。

局部變量

無需在函數中使用全局變量,函數內部使用的任何變量均可以被聲明成局部變量。要實現這
一點,只要在變量聲明的前面加上local關鍵字就能夠了。

也能夠在變量賦值語句中使用local關鍵字:

local temp=$[ $value + 5 ]

local關鍵字保證了變量只侷限在該函數中。若是腳本中在該函數以外有一樣名字的變量,
那麼shell將會保持這兩個變量的值是分離的。如今你就能很輕鬆地將函數變量和腳本變量隔離開
了,只共享須要共享的變量。

[root@xavi ~]# vim test9.sh

#!/bin/bash
# demonstrating the local keyword
function func1 {
local temp=$[ $value + 5 ]
result=$[ $temp * 2 ]
}
temp=4
value=6
func1
echo "The result is $result"
if [ $temp -gt $value ]
then
echo "temp is larger"
else
echo "temp is smaller"
fi

運行結果:
[root@xavi ~]# sh test9.sh
The result is 22
temp is smaller

如今,在func1函數中使用$temp變量時,並不會影響在腳本主體中賦給$temp變量的值。

2、數組變量和函數

2.1 數組的操做(數組注意第一個實際上是a[0] ,這和awk 是不同的)

[root@xavi ~]# b=(1 2 3 4) //定義一個數組a並賦值 1 2 3
[root@xavi ~]# echo ${b[*]} //注意輸出a的值的格式
1 2 3 4
[root@xavi ~]# echo ${b[0]} //注意第一個實際上是 b[0]開始
1
[root@xavi ~]# echo ${b[1]}
2
[root@xavi ~]# echo ${b[@]}
1 2 3 4
[root@xavi ~]# echo ${#b[@]} //獲取數組的元素個數
4
[root@xavi ~]# echo ${#b[*]} //獲取數組的元素個數
4

2.2 給數組賦值,重定義

[root@xavi ~]# b[3]=a
[root@xavi ~]# echo ${b[3]}
a
[root@xavi ~]# echo ${b[*]}
1 2 3 a
[root@xavi ~]# b[4]=a
[root@xavi ~]# echo ${b[*]}
1 2 3 a a

2.3 數組元素的刪除

[root@xavi ~]# unset b[2] //刪除摸個數組元素
[root@xavi ~]# echo ${b[*]}
1 2 a a
[root@xavi ~]# unset b  //刪除整個數組
[root@xavi ~]# echo ${b[*]}

2.4 數組的分片

[root@xavi ~]# a=(`seq 1 10`)
[root@xavi ~]# echo ${a[*]}
1 2 3 4 5 6 7 8 9 10
[root@xavi ~]# echo ${a[@]:3:4} //從第數組a[3]開始,截取4個。
4 5 6 7
[root@xavi ~]# echo ${a[@]:0-3:2} //從倒數第三個數組開始,截取兩個
8 9

[root@xavi ~]# echo ${a[@]/8/6} //把8換成6
1 2 3 4 5 6 7 6 9 10

2.5 向函數傳數組參數:

向腳本函數傳遞數組變量的方法會有點很差理解。將數組變量看成單個參數傳遞的話,它不
會起做用。

[root@xavi ~]# vim badtest3.sh

#!/bin/bash
# trying to pass an array variable
function testit {
echo "The parameters are: $@"
thisarray=$1
echo "The received array is ${thisarray[*]}"
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
testit $myarray

運行:
[root@xavi ~]# sh badtest3.sh
The original array is: 1 2 3 4 5
The parameters are: 1
The received array is 1

若是你試圖將該數組變量做爲函數參數,函數只會取數組變量的第一個值。
要解決這個問題,你必須將該數組變量的值分解成單個的值,而後將這些值做爲函數參數使
用。在函數內部,能夠將全部的參數從新組合成一個新的變量。下面是個具體的例子。

[root@xavi ~]# vim test11.sh
#!/bin/bash
# array variable to function test
function testit {

local newarray
newarray=(`echo "$@"`)
echo "The new array value is: ${newarray[*]}"
}
myarray=(1 2 3 4 5)
echo "The original array is ${myarray[*]}"
testit ${myarray[*]}

運行結果:
[root@xavi ~]# sh test11.sh
The original array is 1 2 3 4 5
The new array value is: 1 2 3 4 5

該腳本用$myarray變量來保存全部的數組元素,而後將它們都放在函數的命令行上。該函
數隨後從命令行參數中重建數組變量。在函數內部,數組仍然能夠像其餘數組同樣使用。

[root@xavi ~]# !vim
vim test12.sh

#!/bin/bash
# adding values in an array
function addarray {
local sum=0
local newarray
newarray=($(echo "$@"))
for value in ${newarray[*]}
do
sum=$[ $sum + $value ]
done
echo $sum
}
myarray=(1 2 3 4 5)
echo "The original array is: ${myarray[*]}"
arg1=$(echo ${myarray[*]})
result=$(addarray $arg1)
echo "The result is $result"

運行結果:
[root@xavi ~]# sh test12.sh
The original array is: 1 2 3 4 5
The result is 15
相關文章
相關標籤/搜索