シェル関数とそのスコープおよびパラメーターの受け渡し、再帰、関数ライブラリの作成
1つはシェル機能
シェルスクリプトを作成するとき、同じコードが複数の場所で使用されていることに気付くことがよくあります。ほんの小さなコードであれば、通常は問題ではありません。しかし、シェルスクリプトでコードの大きなブロックを複数回書き直すのは面倒です。bashシェルによって提供されるユーザー定義関数は、この問題を解決できます。シェルスクリプトコードは関数にカプセル化できるため、スクリプト内のどこでも複数回使用できます。
- 関数を呼び出す
関数はスクリプトコードブロックであり、名前を付けてコード内のどこでも再利用できます。スクリプトでコードブロックを使用する場合は、関数の名前を使用するだけです。
2つ目は、関数を作成する
1.シェル関数形式
第一种格式:
function 函数名 {
命令序列
}
第二种格式:
函数名() {
命令序列
}
2.関数の戻り値
returnは、関数を終了して終了値を返すことを意味します。これは、スクリプトの$?変数で表示できます。
使用原則:
1)$?変数は最後に実行されたコマンドの終了ステータスコードのみを返すため、戻り値は関数が終了するとすぐに取得されます
。2)終了ステータスコードは0〜255である必要があり、値はを超える場合は256で除算します
例1:
[root@localhost ~]#vim hs1.sh
[root@localhost ~]#chmod +x hs1.sh #赋予执行权限
[root@localhost ~]#cat hs1.sh #查看脚本内容
#!/bin/bash
function db1 { #db1是函数名
read -p "请输入:" value #value是变量名
return $[$value * 2] #直接用value乘以2的值作为返回值
}
#####main#####
db1 #调用函数db1
echo $? #输出上个命令的执行结果返回值
[root@localhost ~]#sh -vx hs1.sh #-v:执行脚本前输出脚本内容;-x:列出执行过程
#!/bin/bash
function db1 {
read -p "请输入:" value
return $[$value * 2]
}
db1
+ db1
+ read -p $'\350\257\267\350\276\223\345\205\245\357\274\232' value
请输入:3
+ return 6
echo $?
+ echo 6
6
例2:
[root@localhost ~]#vim hs2.sh
[root@localhost ~]#cat hs2.sh #查看脚本内容
#!/bin/bash
db1() { #db1是函数名
read -p "请输入:" value #value是变量
echo $[$value * 2] #直接输出2乘value的结果
}
result=`db1` #把函数得出的值直接赋给变量result
echo $result #输出result的值
[root@localhost ~]#sh -n hs2.sh #查看脚本有无语法错误
[root@localhost ~]#sh -x hs2.sh #查看脚本执行过程
++ db1
++ read -p $'\350\257\267\350\276\223\345\205\245\357\274\232' value
请输入:10
++ echo 20
+ result=20
+ echo 20
20
[root@localhost ~]#chmod +x hs2.sh #赋给脚本执行权限
[root@localhost ~]#./hs2.sh #执行脚本
请输入:10
20
3、転送パラメータ
bashシェルは関数を小さなスクリプトとして扱います。つまり、通常のスクリプトのように関数にパラメーターを渡すことができます。関数は、標準のパラメーター環境変数を使用して、コマンドラインから関数にアップロードされたパラメーターを表すことができます。たとえば、関数名は$ 0変数で定義され、関数コマンドラインのパラメーターは$ 1、2などで定義されます。また、特別な変数2などで定義することもできます。特別な変数も利用できます2およびその他の固定された意味。またをすることができますすることに使用特特殊な変数の量の#は関数に渡される引数の数を決定します。
[root@localhost ~]#vim hschuancan.sh
[root@localhost ~]#cat hschuancan.sh #查看脚本内容
#!/bin/bash
sum () { #函数名为sum
su=$[$1 + $2] #$1和$2求和以后的值赋给变量su
echo $su #输出变量su的值
}
#########main##########
sum $1 $2 #这段是主代码,调用函数sum,sum函数名后跟着两个参数$1、$2
[root@localhost ~]#chmod +x hschuancan.sh #赋予执行权限
[root@localhost ~]#sh -n hschuancan.sh #查是否有语法错误
[root@localhost ~]#./hschuancan.sh 8 9 #脚本后跟两个参数$1是8,$2是9
17 #执行结果是17
スクリプトが実行されると、次の2つのパラメーターがスクリプトのメインコードに渡されます。つまり、2つのパラメーターの後に合計が続き、関数が実行されると、関数はメインコードの合計に続く2つのパラメーターを参照します。つまり、1ドルと2ドル
注:このスクリプトは、最初にメインの合計$ 1 $ 2を実行し、次に上記で定義された関数sum()を実行します。
第四に、関数変数のスコープ
- シェルスクリプトの関数は、現在のシェル環境でのみ有効です
- シェルスクリプトの変数は、デフォルトでグローバルに有効です
- ローカルコマンドを使用して、変数を関数に制限します
[root@localhost ~]#sh -vx hs3.sh
#!/bin/bash
abc () {
echo "函数内部第一个i的值:$i"
i=$[$i+1]
echo "函数内部第二个i的值:$i"
local i #设置局部变量
i=8
echo "内部第三个i的值:$i"
}
######main######
i=9 #全局环境
+ i=9
abc
+ abc
+ echo $'\345\207\275\346\225\260\345\206\205\351\203\250\347\254\254\344\270\200\344\270\252i\347\232\204\345\200\274\357\274\2329'
函数内部第一个i的值:9 #先i=9作为全局变量的时候调用函数abc,所以这里的i依然是全局变量
+ i=10 #这里i=$[$i+1],依然是全局变量
+ echo $'\345\207\275\346\225\260\345\206\205\351\203\250\347\254\254\344\272\214\344\270\252i\347\232\204\345\200\274\357\274\23210'
函数内部第二个i的值:10 #还没设置局部变量,这是刚刚运算得出的值
+ local i #设置局部变量
+ i=8 #局部变量值为8,不影响外部的全局变量
+ echo $'\345\206\205\351\203\250\347\254\254\344\270\211\344\270\252i\347\232\204\345\200\274\357\274\2328'
内部第三个i的值:8 #局部变量值为8
echo "函数外部i的值:$i"
+ echo $'\345\207\275\346\225\260\345\244\226\351\203\250i\347\232\204\345\200\274\357\274\23210'
函数外部i的值:10 #外部全局变量调用函数以后它的值加1
[root@localhost ~]#cat hs3.sh
#!/bin/bash
abc () {
echo "函数内部第一个i的值:$i"
i=$[$i+1]
echo "函数内部第二个i的值:$i"
local i #设置局部变量
i=8
echo "内部第三个i的值:$i"
}
######main######
i=9 #全局环境
abc
echo "函数外部i的值:$i"
注:ローカルとグローバルは2種類の変数であり、異なる値を割り当てることができますが、同じ名前にすることができます
5、再帰階乗
関数はそれ自体を呼び出して結果を取得できます。通常、再帰関数には、最終的に反復できるベースライン値があります。再帰的アルゴリズムの典型的な例は、階乗を計算することです。数値の階乗は、その数値の前にあるすべての数値に、5の階乗などの数値を掛けた値です。
5! = 5 * 4 * 3 * 2 * 1
再帰の使用は、次の形式に簡略化できます。
x! = x * (x-1)!
原理を理解した後は、比較的簡単に実行できるため、次のスクリプトで記述されます。
例として3の階乗を取り上げます
[root@localhost ~]#vim jc.sh
[root@localhost ~]#cat jc.sh
fact () {
if [ $1 -eq 1 ] #等于1的时候输出1,不等于的时候进入else
then
echo 1
else #下面定义两个局部变量,只在当前函数内部有效
local temp=$[$1 - 1]
local result=$(fact $temp)
echo $[$1 * $result] #当n=3,也就相当于(3*result(2*result(1)))
fi
}
read -p "请输入:" n
result=$(fact $n)
echo $result
[root@localhost ~]#sh -x jc.sh
+ read -p $'\350\257\267\350\276\223\345\205\245\357\274\232' n
请输入:3
++ fact 3
++ '[' 3 -eq 1 ']'
++ local temp=2
+++ fact 2
+++ '[' 2 -eq 1 ']'
+++ local temp=1
++++ fact 1
++++ '[' 1 -eq 1 ']'
++++ echo 1
+++ local result=1
+++ echo 2
++ local result=2
++ echo 6
+ result=6
+ echo 6
6
6つの再帰ディレクトリ
[root@localhost ~]#vim dgml.sh
[root@localhost ~]#cat dgml.sh
#!/bin/bash
function list_files () {
for f in `ls $1`
do
if [ -d "$1/$f" ]
then
echo "$2$f" #如果是目录就输出这个目录,$2为空格是用于区分父子目录
list_files "$1/$f" " $2" #如果想区分的明显点,可在$2前面加空格
else
echo "$2$f" #不是目录则输出$f结果
fi
done
}
list_files "/var/log" ""
[root@localhost ~]#./dgml.sh #执行脚本,目录和子目录分明
anaconda
anaconda.log
ifcfg.log
journal.log
ks-script-1Pn8cs.log
ks-script-W4EI_q.log
packaging.log
program.log
storage.log
syslog
X.log
audit
audit.log
セブン、ライブラリを作成する
[root@localhost ~]#cat hsku.sh
#!/bin/bash
jiafa () {
echo $[$1 + $2]
}
chengfa () {
echo $[$1 * $2]
}
chufa () {
if [ $2 -ne 0 ];then
echo $[$1 / $2]
else
echo "$2不能为0"
fi
}
[root@localhost ~]#cat fuzhi.sh
#!/bin/bash
. hsku.sh
value1=10
value2=5
result1=`jiafa $value1 $value2`
result2=`chengfa $value1 $value2`
result3=`chufa $value1 $value2`
echo "加法结果为: $result1"
echo "乘法结果为: $result2"
echo "除法结果为: $result3"
[root@localhost ~]#./fuzhi.sh
加法结果为: 15
乘法结果为: 50
除法结果为: 2