shell指令碼之四:shift位置引數左移、函式、退出迴圈
1、Shift位置引數左移指令
1.1、定義:
shift命令用於對位置引數的移動(左移),通常用於在不知道傳入引數個數的情況下依次遍歷每個引數然後進行相應處理。
1.2、作用:
每執行一次,位置引數序列順次左移一個位置,$#的值減1,用於分別處理每個引數,移出去的引數,不再可用,例如執行一次shift位置引數就左移一次,原來的第一個位置引數被移出去了,不再可用,第二個位置引數成了第一個位置引數,依次類推。
1.3、例項:加法計算器
[root@localhost ~]# cat shift.sh
#!/bin/bash
if [ $# -le 0 ];then
echo "沒有提供足夠的引數"
exit 1
fi
sum=0
while [ $# -gt 0 ];do
sum=$[$sum+$1]
shift
done
echo “result is $sum”
[root@localhost ~]# sh shift.sh
沒有提供足夠的引數
result is 0
[root@localhost ~]# sh shift.sh 2 3 8 10
result is 23
[root@localhost ~]# sh shift.sh 2 3 8 -10 5
result is 8
[root@localhost ~]# cat shift.sh
#!/bin/bash
if [ $# -le 0 ];then
echo "沒有提供足夠的引數"
exit 1
fi
sum=0
while [ $# -gt 0 ];do
#sum=$[$sum+$1]
sum=$(expr $sum + $1)
#shift 2 一次移動2個引數
shift
done
echo result is $sum
2、函式的使用
函式是一個指令碼程式碼塊,你可以對它進行自定義命名,並且可以在指令碼中任意位置使用這個函式,要使用這個函式,只要使用這個函式名稱就可以了
函式:把一個功能封裝起來。使用時直接呼叫函式名。這樣的指令碼好處:模組化,程式碼可讀性強。
2.1、函式建立
兩種·建立函式的方法:
方法一:
function name() {
命令序列
[return value]
}
方法二:
name() {
命令序列
[return value]
}
注意:
1、其中function是可選的,這個可以省略掉。name是函式唯一的名稱,函式名後面加一個(),裡面是沒有內容的。而我們執行的命令序列放在{}裡面的,由{ }包圍的部分稱為函式體,呼叫一個函式,實際上就是執行函式體中的程式碼。return value表示函式的返回值,其中 return 是 Shell 關鍵字,專門用在函式中返回一個值;這一部分可以寫也可以不寫。
2、在定義函式的時候,必須要在執行程式前面定義或載入(即必須在呼叫函式地方之前,定義好函式)
3、在執行函式時(呼叫函式),函式前面的function和函式後面的小括號都不要寫,直接寫函式名就可以了
2.2、函式的使用
2.2.1、建立一個函式
[root@localhost ~]# cat fun-1.sh
#!/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 while"
func1 #呼叫函式
echo "Now this is the end of the script"
[root@localhost ~]# sh fun-1.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 while
This is an example of a function
Now this is the end of the script
2.2.2、函式返回值:函式的退出狀態
預設情況下,函式的退出狀態是函式的最後一條命令返回的退出狀態。
[root@localhost ~]# cat fun-2.sh
#!/bin/bash
# testing the exit status of a function
func1() {
echo "trying to display a non-existent file"
ls -l badfile
}
echo "testing the function:"
func1
echo "The exit status is: $?"
[root@localhost ~]# sh fun-2.sh
testing the function:
trying to display a non-existent file
ls: cannot access badfile: No such file or directory
The exit status is: 2
2.2.3、函式返回值:return命令返回特定的退出碼
我們可以通過return命令來退出函式並返回特定的退出碼
return命令可以使用單個整數值來定義函式退出狀態,提供了一種通過程式設計設定函式退出狀態的簡單方法。
注:return語句返回一個退出值給呼叫函式的程式,而exit的返回值是給執行程式當前的SHELL
[root@localhost ~]# cat fun-3.sh
#!/bin/bash
fun1(){
ls badfile
return 2
echo "This is apple"
return 5
}
fun1
echo result is $?
[root@localhost ~]# sh fun-3.sh
ls: cannot access badfile: No such file or directory
result is 2
在使用這個返回狀態碼的時候,要注意以下2點:
狀態碼必須要在函式一結束就進行取值。
狀態碼的取值範圍(0~255)
2.3、把函式值賦給變數使用
正如命令輸出可以捕獲並存放到 shell 變數中一樣,函式的輸出也可以捕獲並存放到 shell 變數中。
範例1:
[root@localhost ~]# cat fun-4.sh
#!/bin/bash
fun1(){
read -p "Input a value: " VAR
echo $[$VAR*5]
}
NUM=$(fun1)
echo current num is $NUM
[root@localhost ~]# sh fun-4.sh
Input a value: 10
current num is 50
2.4、向函式傳遞引數
2.4.1、 第一種情況
函式可以使用位置引數變數來表示要傳遞給函式的引數。
函式名在變數 $0 中定義, 函式命令列的其他引數使用變數 $1、$2..., $#可以用來確定傳遞給函式的引數數目。
[root@localhost ~]# cat fun-5.sh
#!/bin/bash
function addem() {
if [ $# -eq 0 ] || [ $# -gt 2 ]
then
echo "error,need to input one or two number."
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@localhost ~]# sh fun-5.sh
Adding 10 and 15: 25
Let's try adding just one number: 20
Now trying adding no numbers: error,need to input one or two number.
Finally, try adding three numbers: error,need to input one or two number.
2.4.2、 第二種情況
函式無法從指令碼命令列(shell提示符中)直接訪問指令碼引數值。如果想在函式中使用這些值,那麼必須在呼叫該函式時手動傳遞這些資料。
[root@localhost ~]# cat fun-6.sh
#!/bin/bash
# trying to access script parameters inside a function
function func6 {
echo $[ $1 * $2 ]
}
if [ $# -eq 2 ]
then
value=`func6 $1 $2`
echo "The result is $value"
else
echo "Usage: badtest1 a b"
fi
[root@localhost ~]# sh fun-6.sh 4 6
The result is 24
3、跳出迴圈
在我們使用迴圈語句進行迴圈的過程中,有時候需要在未達到迴圈結束條件時強制跳出迴圈,那麼Shell給我們提供了兩個命令來實現該功能:break和continue
注:exit:退出當前整個指令碼的
3.1、Break
結束並跳出當前迴圈,在for
、
while
等迴圈語句中,用於跳出當前所在的迴圈體,執行迴圈體之後的語句,後面如果什麼也不加,表示跳出當前迴圈等價於break 1,也可以在後面加數字,假設break 3表示跳出三層迴圈
範例1:
[root@localhost ~]# cat break.sh
#!/bin/bash
while true
do
read -p "Enter a number [1-5]:" num
case $num in
1|2|3|4|5)
echo "GREATER"
;;
*)
echo "wrong...Bye"
break
esac
done
[root@localhost ~]# sh break.sh
Enter a number [1-5]:3
GREATER
Enter a number [1-5]:4
GREATER
Enter a number [1-5]:5
GREATER
Enter a number [1-5]:1
GREATER
Enter a number [1-5]:2
GREATER
Enter a number [1-5]:3
GREATER
Enter a number [1-5]:34
wrong...Bye
3.2、Continue
它和break命令差不多,忽略本次迴圈剩餘的程式碼,直接進行下一次迴圈;在for
、
while
等迴圈語句中,用於跳出當次迴圈,直接進入下一次迴圈。
範例2:
[root@localhost ~]# cat continue.sh
#!/bin/bash
while true
do
echo -n "Input a number between 1 to 5: "
read aNum
case $aNum in
1|2|3|4|5) echo "Your number is $aNum!"
;;
*)
echo "You do not select a number between 1 to 5!"
continue
echo "Game is over!"
;;
esac
done
範例3:新增使用者的指令碼
[root@localhost ~]# cat add_user.sh
#!/bin/bash
while true
do
read -p "Please enter prefix & passwd & number: " pre pass num
printf "user information:
***********************
user prefix: $pre
user password: $pass
user number: $num
"
read -p "Are you sure?[y/n] " action
if [ "$action" == "y" ];then
break
fi
done
#adduser
for i in $(seq -w $num)
do
user=${pre}${i}
id $user &> /dev/null
if [ $? -ne 0 ];then
useradd $user
echo "$pass"|passwd --stdin $user &> /dev/null
if [ $? -eq 0 ];then
echo -e "\e[31m$user\e[0m create"
fi
else
echo "User $user exist"
fi
done
執行指令碼:
刪除使用者:
[root@localhost ~]# for i in `seq -w 1 11`;do userdel -r tech$i;done