shell學習[三]:流程控制語句與函式
1.Shell整數計算命令
1.1 expr表示式求值命令
expr (evaluate expressions 的縮寫),譯為“表示式求值”。Shell expr 是一個功能強大,並且比較複雜的命令,它除了可以實現整數計算,還可以結合一些選項對字串進行處理,例如計算字串長度、字串比較、字串匹配、字串提取等.
計算語法
expr 算術運算子表示式
# 例如: expr 1 + 1 返回: 2
# 例如: expr \( 10 + 10 \) \* 2 + 100 返回:140
abc@aliyun:~$ expr \( 10 + 10 \) \* 2 + 100
140
獲取計算結果賦值給新變數語法
result=`expr 算術運算子表示式` # 例如: result=`expr 1 + 1` 輸出result得到結果: 2
計算字串的長度語法
expr length 字串
# 例如: expr length "itheima" 返回: 7
擷取字串語法
expr substr 字串 start end
# start 擷取字串的起始位置, 從1開始
# end 擷取字串的結束位置, 包含這個位置擷取
# 例如 expr substr "itheima" 1 2 返回: it
獲取第一個字元在字串中出現的位置語法
expr index 被查詢字串 需要查詢的字元
# 例如 expr index "itheima" t 會返回: 2
正則表示式匹配1語法
expr match 字串 正則表示式 # 正則表示式預設帶有^ , 代表以什麼開頭 # 返回值為符合匹配字元的長度, 否則返回為0 # 例如: expr match "itheima" ".*m" 會返回: 6 # 正則表示式萬用字元"."代表任意一個字元 # 正則表示式萬用字元"*"代表簽名的字元可以出現0到多次 # ".*m" 含義為匹配字串中m前面的字串長度
正則表表達式匹配2語法, 功能與語法1一樣
expr 字串 : 正則表示式
# 正則表示式預設帶有^ , 代表以什麼開頭
# 返回值為符合匹配字元的長度, 否則返回為0
# 例如: expr "itheima" : ".*m" 會返回: 6
演示
#!/bin/bash # 四則運算 result=`expr \( 10 + 10 \) \* 2 + 100` echo "(10+10)*2+100=${result}" # 計算字串的長度 echo "itheima字串長度=`expr length "itheima"`" # 獲取第一個字元在字串中出現的位置 echo "itheima字串中第一個t的位置=`expr index "itheima" t`" # 正則表示式匹配1 echo "正則表示式match匹配查詢itheima字串中m前面任意字元的總長度=`expr match "itheima" ".*m"`" # 正則表示式匹配2 echo "正則表示式匹配查詢itheima字串中m前面任意字元的總長度=`expr "itheima" : ".*m"`"
1.2 (())命令詳解
雙小括號 (( )) , 用於進行數學運算表示式的執行 , 將數學運算表示式放在((
和))
之間。
可以使用$
獲取 (( )) 表示式命令的結果,這和使用$
獲得變數值是一樣的。
語法
((表示式))
用法
運算操作符/運算命令 | 說明 |
---|---|
((a=1+6)) ((b=a-1)) ((c=a+b)) |
這種寫法可以在計算完成後給變數賦值。以 ((b=a-1)) 為例, 即將 a-1 的運算結果賦值給變數 c。 注意,使用變數時不用加 $ 字首,(( )) 會自動解析變數名。 |
a=$((1+6) b=$((a-1)) c=$((a+b))
|
可以在 (( )) 前面加上$ 符號獲取 (( )) 命令的執行結果,也即獲取整個表示式的值。以 c=$((a+b)) 為例,即將 a+b 這個表示式的運算結果賦值給變數 c。 注意,如果 c=((a+b)) 這樣的寫 法是錯誤的,不加 $ 就不能取得表示式的結果。 |
((a>7 && b==c)) | (( )) 也可以進行邏輯運算,在 if 語句中常會使用邏輯運算。 |
echo $((a+10)) | 需要立即輸出表達式的運算結果時,可以在 (( )) 前面加$ 符號。 |
((a=3+5, b=a+10)) | 對多個表示式同時進行計算, 多表表示式使用","號隔開 |
注意: 符號之間有無空格都可以 , (( a = 1 + 6 )) 等價於 ((a=1+6))
示例
#!/bin/bash
# 計算1+6賦值給變數a
((a=1+6))
# 計算變數a-1賦值給變數b
((b=a-1))
# 計算變數a+變數b賦值給變數c
((c=a+b))
# 列印變數a,變數b, 變數c的值
echo "a=${a},b=${b},c=${c}"
# $賦值寫法
a=$((1+6)) b=$((a-1)) c=$((a+b))
echo "a=${a},b=${b},c=${c}"
# (())多個表示式計算賦值
((a=1+6,b=a-1,c=a+b))
echo "a=${a},b=${b},c=${c}"
# echo輸出直接使用(())
echo "1+6=$((1+6))"
# (()) 用於邏輯表示式 在if中使用
if ((a>7 && b==c))
then
echo "a>7 && b==c 成立"
else
echo "a>7 && b==c 不成立"
fi
1.3 let命令詳解
let 命令和雙小括號 (( )) 在數字計算方面功能一樣. 但是沒有(())功能強大, let只能用於賦值計算, 不能直接輸出, 不可以條件判斷一起使用
語法
let 賦值表示式
注意
語法功能等價於
((表示式))
多個表示式之間使用空格, 不是","號
對於類似
let a+b
這樣的寫法,Shell 雖然計算了 a+b 的值,但卻將結果丟棄, 如果echo let a+b
會直接輸出字串a+b
;若不想這樣,可以使用let sum=a+b
將 a+b 的結果儲存在變數 sum 中。abc@aliyun:~$ a=1 b=2 abc@aliyun:~$ echo let a+b let a+b abc@aliyun:~$ echo $((a+b)) 3 abc@aliyun:~$
輸出建議使用(())
示例
#!/bin/bash
# 計算1+6賦值給變數a
let a=1+6
# 計算變數a-1賦值給變數b
let b=a-1
# 計算變數a+變數b賦值給變數c
let c=a+b
# 列印變數a,變數b, 變數c的值
echo "a=${a},b=${b},c=${c}"
# let多個表示式計算賦值
let a=1+6 b=a-1 c=a+b
echo "a=${a},b=${b},c=${c}"
1.4 $[]命令詳解
和 (())、let 命令類似,$[] 也只能進行整數運算。但是隻能對單個表示式的計算求值與輸出
語法
$[表示式]
$[] 會對
表示式
進行計算,並取得計算結果表示式內部不可以賦值給變數
示例
#!/bin/bash
# 計算1+6賦值給變數a
a=$[1+6]
# 計算變數a-1賦值給變數b
b=$[a-1]
# 計算變數a+變數b賦值給變數c
c=$[a+b]
# 列印變數a,變數b, 變數c的值
echo "a=${a},b=${b},c=${c}"
# 直接輸出
echo "$[1+6],$[7-1],$[7+6]"
1.5 bc命令詳解
Bash shell內建了對整數運算的支援,但是並不支援浮點運算,而 linux bc (basic calculator)命令可以很方便的進行浮點運算. bc命令是Linux簡單的計算器,能進行進位制轉換與計算。能轉換的進位制包括十六進位制、十進位制、八進位制、二進位制等。可以使用的運算子號包括(+)加法、(-)減法、(*)乘法、(/)除法、(^)指數、(%)餘數等
語法
bc [options] [引數]
options
選項 | 說明 |
---|---|
-h | help,幫助資訊 |
-v | version,顯示命令版本資訊 |
-l | mathlib, 使用標準數學庫, 例如使用內建函式就需要使用這個引數 |
-i | interactive, 強制互動 |
-w | warn, 顯示 POSIX 的警告資訊 |
-s | standard, 使用 POSIX 標準來處理 |
-q | quiet, 不顯示歡迎資訊 |
預設使用bc命令後回車會有很多歡迎資訊, 可以使用
bc -q
回車後不會有歡迎資訊
引數
檔案: 指定包含計算任務的檔案。
示例:bc執行計算任務的檔案
建立task.txt檔案, 編輯檔案內容(一個計算表示式一行)
108*67+12345
58+2007*11
執行命令
abc@aliyun:/tmp/bgtest$ bc -q cal.txt
19581
22135
可以使用
quit
命令退出bc
內建變數
變數名 | 作 用 |
---|---|
scale | 指定精度,也即小數點後的位數, 對計算結果指定保留小數;預設為 0,也即不使用小數部分。 |
ibase | 指定輸入的數字的進位制,預設為十進位制。 |
obase | 指定輸出的數字的進位制,預設為十進位制。 |
last 或者 . | 獲取最近計算列印結果的數字 |
內建數學函式
函式名 | 作用 |
---|---|
s(x) | 計算 x 的正弦值,x 是弧度值。 |
c(x) | 計算 x 的餘弦值,x 是弧度值。 |
a(x) | 計算 x 的反正切值,返回弧度值。 |
l(x) | 計算 x 的自然對數。 |
e(x) | 求 e 的 x 次方。 |
j(n, x) | 貝塞爾函式,計算從 n 到 x 的階數。 |
作用
通常在linux下bc當計算器用, 具體有3個用法
- bc中互動式的數學運算
- shell中非互動式的管道運算
- shell中非互動式的輸入重定向運算
示例1:bc中互動式的數學運算
使用 bc -q
命令,回車即可, 直接進行計算器進行運算
abc@aliyun:/tmp/bgtest$ bc -q
1+1 #加
2
2^3 #冪運算
8
10/3 #除
3
10%3 #取餘數
1
m=2;n=3;m+n #定義變數
5
scale=4;10/3 #設定小數保留4位
3.3333
ibase=2;7
7
ibase=2;111 #設定輸入為2進位制
7
obase=2;7 #設定輸出為2進位制
111
退出bc使用 quit
#使用標準數學庫, 例如使用內建函式就需要使用這個引數
abc@aliyun:/tmp/bgtest$ bc -q -l
e(5) #求e的5次方
148.41315910257660342111
s(5) #求5的正弦值
-.95892427466313846889
j(5,10) #貝塞爾函式,計算從 5 到 10 的階數
-.23406152818679364044
l(5) #計算 5 的自然對數。
1.60943791243410037460
示例2:shell中非互動式的管道運算
在 Shell 指令碼中,我們可以藉助管道使用 bc 計算器。
藉助管道使用 bc 計算器語法
直接進行bc的表示式計算輸出
echo "expression" | bc [options]
"expression" 表示式必須符合bc命令要求的公式
"expression" 表示式裡面可以引用shell變數
例如: Shell變數
a=2
在表示式裡面引用的語法:$a
將bc計算結果賦值給Shell變數
# 第一種方式
var_name=`echo "expression" | bc [options]`
# 第二種方式
var_name=$(echo "expression" | bc [options])
$() 與 `` 功能一樣, 都是執行裡面的命令
區別
`` (tab鍵上面的符號)是所有linux系統支援的方式, 相容性較好, 但是容易與引號產生混淆
$() 不是所有linux系統都支援的方式, 相容性較差, 但是不容易產生混淆
演示
abc@aliyun:/tmp/bgtest$ echo "9*9"|bc
81
abc@aliyun:/tmp/bgtest$ result=$(echo "4+9"|bc)
abc@aliyun:/tmp/bgtest$ echo $result
13
abc@aliyun:/tmp/bgtest$ echo "scale=3;10/3"|bc
3.333
abc@aliyun:/tmp/bgtest$ echo "scale=3;10/3;last*2"|bc
3.333
6.666
abc@aliyun:/tmp/bgtest$
引用shell變數進行計算
abc@aliyun:/tmp/bgtest$ a=2
abc@aliyun:/tmp/bgtest$ echo "scale=2;b=$a+2;e(b)"|bc -l
54.59
abc@aliyun:/tmp/bgtest$ echo "scale=2;e(4)"|bc -l
54.59
注意 b是bc中定義的新變數, 與shell變數沒有任何關係, 所以不可以在shell中獲取b變數
進位制轉換
abc@aliyun:/tmp/bgtest$ a=111
abc@aliyun:/tmp/bgtest$ b=$(echo "ibase=2;$a"|bc) #2進位制轉10進位制
abc@aliyun:/tmp/bgtest$ echo $b
7
abc@aliyun:/tmp/bgtest$ a=7
abc@aliyun:/tmp/bgtest$ b=$(echo "ibase=10;obase=2;$a"|bc) #10進位制轉2進位制
abc@aliyun:/tmp/bgtest$ echo $b
111
示例3:shell中非互動式的輸入重定向運算
將計算表示式輸出給bc去執行, 特點類似於檔案中輸入,可以輸入多行表示式, 更加清晰
語法
# 第一種方式
var_name=`bc [options] << EOF
第一行表示式1
第二行表示式2
...
EOF
`
# 第二種方式
var_name=$(bc [options] << EOF
第一行表示式1
第二行表示式2
...
EOF
)
var_name
這是Shell變數的名字
bc
執行bc的命令
EOF..EOF
輸入流的多行表示式含義: 將EOF中間多行表示式輸入給到bc去執行, j將bc執行的結果給到Shell變數var_name
演示
[root@aliyun ~]# a=100
[root@aliyun ~]# b=$(bc << EOF
> ibase=10;
> obase=2;
> $a
> EOF
> )
[root@aliyun ~]# echo $b
1100100
如果有大量的數學計算,那麼使用輸入重定向就比較方便,因為數學表示式可以換行,寫起來更加清晰。
2.流程控制語句
2.1 if else語句
if語法
多行寫法語法
if 條件
then
命令
fi
可以將if語句放入一行語法
if 條件; then 命令; fi
if else 語法
if 條件
then
命令
else
命令
fi
if elif else 語法
if 條件1
then
命令1
elif 條件2
then
命令2
elif 條件3
then
命令3
……
else
命令N
fi
演示
#!/bin/bash
read -p "請輸入你的考試成績:" score
if (( $score < 60 )); then
echo "不及格"
elif (( $score >= 60 && $score < 70 )); then
echo "及格"
elif (( $score >= 70 && $score < 80 )); then
echo "中等"
elif (( $score >= 80 && $score < 90 )); then
echo "良好"
elif (( $score >= 90 && $score <= 100 )); then
echo "優秀"
else
echo "成績不合法"
fi
(())
是一種數學計算命令,它除了可以進行最基本的加減乘除運算,還可以進行大於、小於、等於等關係運算,以及與、或、非邏輯運算。當 a 和 b 相等時,(( $a == $b ))
判斷條件成立,進入 if,執行 then 後邊的 echo 語句
if條件判斷句的退出狀態
linux任何命令的的執行都會有一個退出狀態, 無論是內建命令還是外部檔案命令. 還是自定義的 Shell 函式,當它退出(執行結束)時,都會返回一個比較小的整數值給呼叫(使用)它的程式,這就是命令的退出狀態
大多數命令狀態0代表成功, 非0代表失敗. 也有特殊的命令,比如 diff 命令用來比較兩個檔案的不同,對於“沒有差別”的檔案返回 0,對於“找到差別”的檔案返回 1,對無效檔名返回 2
Shell 中,有多種方式取得命令的退出狀態,其中 $?
是最常見的一種.
abc@aliyun:/tmp/bgtest$ ((1==2))
abc@aliyun:/tmp/bgtest$ echo $?
1
abc@aliyun:/tmp/bgtest$ ((1==1))
abc@aliyun:/tmp/bgtest$ echo $?
0
abc@aliyun:/tmp/bgtest$ cd ..
abc@aliyun:/tmp$ echo $?
0
退出狀態和邏輯運算子的組合
Shell if 語句使用邏輯運算子將多個退出狀態組合起來,這樣就可以一次判斷多個條件了。
運算子 | 使用格式 | 說明 |
---|---|---|
&& 或 -a | 條件1 && 條件2 | 邏輯與運算子,當 條件1 和 條件2 同時成立時, 整個表示式才成立。 如果檢測到 條件1 的退出狀態為 0, 就不會再檢測 條件2 了,因為不管 條件2 的退出狀態是什麼, 整個表示式必然都是不成立的,檢測了也是多此一舉。 |
|| 或 -o | 條件1 || 條件2 | 邏輯或運算子,條件1 和 條件2 兩個表 達式中只要有一個成立,整個表示式就成立。 如果檢 測到 條件1 的退出狀態為 1,就不會再檢測 條件2 了,因為 不管 條件2 的退出狀態是什麼,整個表示式必然都是成立的, 檢測了也是多此一舉。 |
! | !條件 | 邏輯非運算子,相當於“取反”的效果。如果 條件 成立,那麼整 個表示式就不成立;如果 條件 不成立,那麼整個表示式就成立。 |
示例
提示輸入"請輸入檔案全名: "和"請輸入資料:" 並接收檔名與資料
使用邏輯運算子判斷滿足2 條件 : 檔案需要具有可寫許可權 和 輸入的資料長度不為0
滿足以上2個條件 將使用者輸入的 資料 寫入到指定的檔案中去
#!/bin/bash
read -p "請輸入檔案全名: " filename
read -p "請輸入資料:" data
if [ -w $filename -a -n $data ]
then
echo $data
echo $data > $filename
echo "成功"
else
echo "失敗"
fi
test命令用於對檔案或字串進行檢測,
-w
判斷檔案是否存在並且可寫,-n
用於檢測字串是否非空
$data > $filename
其中>
用於將內容輸出到指定檔案中去
Shell內建命令:test
Shell中的 test 命令用於檢查某個條件是否成立,它可以進行數值、字元和檔案三個方面的測試。
功能與[]一樣
整數比較測試
if test 數字1 options 數字2
then
...
fi
options具體如下
引數 | 說明 |
---|---|
-eq | 等於則為真 |
-ne | 不等於則為真 |
-gt | 大於則為真 |
-ge | 大於等於則為真 |
-lt | 小於則為真 |
-le | 小於等於則為真 |
演示
#!/bin/bash
num1=1 num2=1 num3=2
echo "num1=${num1},num2=${num2},num3=${num3}"
if test $num1 -eq $num2
then
echo 'num1和num2兩個數相等!'
else
echo 'num1和num2兩個數不相等!'
fi
if test $num2 -eq $num3
then
echo 'num2和num3兩個數相等!'
else
echo 'num2和num3兩個數不相等!'
fi
字串比較測試
引數 | 說明 |
---|---|
= 或 == | 等於, 等於返回0代表成功,否則返回1代表失敗 |
!= | 不等於 |
\< |
小於 |
\> |
大於 |
-z 字串 | 字串的長度為零則為真 |
-n 字串 | 字串的長度不為零則為真 |
演示
#!/bin/bash
str1="itheima" str2="itcast" str3=""
echo "str1=${str1},str2=${str2},str3=${str3}"
if test $str1 = $str2
then
echo 'str1和str2兩個字串相等'
else
echo 'str1和str2兩個字串不相等'
fi
if test $str1 \> $str2
then
echo 'str1大於str2'
else
echo 'str1小於str2'
fi
if test -z $str2
then
echo "str2字串長度為0"
else
echo "str2字串長度不為0"
fi
if test -z $str3
then
echo "str3字串長度為0"
else
echo "str3字串長度不為0"
fi
檔案測試
引數 | 說明 |
---|---|
-e 檔名 | exists, 如果檔案存在則為真 |
-r 檔名 | read,如果檔案存在且可讀則為真 |
-w 檔名 | write,如果檔案存在且可寫則為真 |
-x 檔名 | execute,如果檔案存在且可執行則為真 |
-s 檔名 | string,如果檔案存在且至少有一個字元則為真 |
-d 檔名 | directory,如果檔案存在且為目錄則為真 |
-f 檔名 | file,如果檔案存在且為普通檔案則為真 |
-c 檔名 | character,如果檔案存在且為字元型特殊檔案則為真 |
-b 檔名 | 如果檔案存在且為塊特殊檔案則為真 |
演示
#!/bin/bash
if test -w ./control1.sh
then
echo '檔案已存在並且可寫!'
else
echo '檔案不存在或不可寫!'
fi
if test -e ./control1.sh -a -e ./control2.sh
then
echo '兩個檔案都存在!'
else
echo '可能有一個或兩個檔案不存在'
fi
Shell提供了與( -a )、或( -o )、非( ! )三個邏輯操作符用於將測試條件連線起來,其優先順序為:"!"最高,"-a"次之,"-o"最低, 語法
test 條件1 -o 條件2 -a 條件3 ...
2.2 case語句
Shell case語句為多選擇語句。可以用case語句匹配一個值與一個模式,如果匹配成功,執行相匹配的命令;
當分支較多,並且判斷條件比較簡單時,使用 case in 語句就比較方便了。
case 值 in
匹配模式1)
命令1
命令2
...
;;
匹配模式2)
命令1
命令2
...
;;
*)
命令1
命令2
...
;;
esac
每一匹配模式必須以右括號結束。取值可以為變數或常數。匹配發現取值符合某一模式後,其間所有命令開始執行直至 ;;(類似break, 不可以替代否則語法報錯)。取值將檢測匹配的每一個模式。一旦模式匹配,則執行完匹配模式相應命令後不再繼續其他模式。如果無一匹配模式,使用星號 * 捕獲該值,再執行後面的命令。
case、in 和 esac 都是 Shell 關鍵字, esac就是case的反寫在這裡代表結束case
匹配模式: 可以是一個數字、一個字串,甚至是一個簡單正則表示式。
簡單正則表示式支援如下萬用字元
格式 | 說明 |
---|---|
* | 表示任意字串。 |
[abc] | 表示 a、b、c 三個字元中的任意一個。比如,[15ZH] 表示 1、5、Z、H 四個字元中的任意一個。 |
[m-n] | 表示從 m 到 n 的任意一個字元。比如,[0-9] 表示任意一個數字,[0-9a-zA-Z] 表示字母或數字。 |
| | 表示多重選擇,類似邏輯運算中的或運算。比如,abc | xyz 表示匹配字串 "abc" 或者 "xyz"。 |
演示
#!/bin/bash
read -p "請輸入一個0~7的數字:" number
case $number in
1)
echo "星期一"
;;
2)
echo "星期二"
;;
3)
echo "星期三"
;;
4)
echo "星期四"
;;
5)
echo "星期五"
;;
6)
echo "星期六"
;;
0|7)
echo "星期日"
;;
*)
echo "您輸入的數字無效"
;;
esac
2.3 while語句
while用於迴圈執行一系列命令
多行寫法
while 條件
do
命令1
命令2
...
continue; # 結束當前這一次迴圈, 進入下一次迴圈
break; # 結束當前迴圈
done
一行寫法
while 條件; do 命令; done;
演示
#!/bin/bash
read -p "請輸入一個數字:" number
i=0
while [[ $i < $number ]]
do
echo "hello world"
((i++))
done
無限迴圈
while :
do
command
done
或
while true
do
command
done
2.4 until語句
until 也是迴圈結構語句, until 迴圈與 while 迴圈在處理方式上剛好相反, 迴圈條件為false會一致迴圈, 條件為true停止迴圈.
until 條件
do
命令
done
條件如果返回值為1(代表false),則繼續執行迴圈體內的語句,否則跳出迴圈。
演示
#!/bin/bash
read -p "請輸入一個數字:" number
i=0
until [[ ! $i < $number ]]
do
echo "hello world"
((i++))
done
2.5 for語句
Shell支援for迴圈, 與其他程式語言類似.
迴圈方式1
多行寫法
for var in item1 item2 ... itemN
do
命令1
命令2
...
done
一行寫法
for var in item1 item2 ... itemN; do 命令1; 命令2…; done;
var是迴圈變數
item1 item2 ... itemN 是迴圈的範圍
演示
#!/bin/bash
for i in 1 2 3 4 5
do
echo "hello world"
done
迴圈方式2
多行寫法
for var in {start..end}
do
命令
done
start: 迴圈範圍的起始值,必須為整數
end: 迴圈範圍的結束值, 必須為整數
一行寫法
for var in {start..end}; do 命令; done
演示
迴圈1到5並列印
for i in {1..5}; do echo $i; done
迴圈方式3
多行寫法
for((i=start;i<=end;i++))
do
命令
done
一行寫法
for((i=start;i<=end;i++)); do 命令; done
演示
abc@aliyun:~$ for ((i=1;i<=5;i++)); do echo "hello world ${i}"; done
hello world 1
hello world 2
hello world 3
hello world 4
hello world 5
無限迴圈
for((;;)); do 命令; done
2.6 流程控制:select語句
select in 迴圈用來增強互動性,它可以顯示出帶編號的選單,使用者輸入不同的編號就可以選擇不同的選單,並執行不同的功能. select in 是 Shell 獨有的一種迴圈,非常適合終端(Terminal)這樣的互動場景, 其他語言沒有;
select var in menu1 menu2 ...
do
命令
done
注意: select 是無限迴圈(死迴圈),輸入空值,或者輸入的值無效,都不會結束迴圈,只有遇到 break 語句,或者按下 Ctrl+D 組合鍵才能結束迴圈。
執行命令過程中: 終端會輸出
#?
代表可以輸入選擇的選單編號
演示1
#!/bin/bash
echo "你的愛好是什麼?"
select hobby in "程式設計" "遊戲" "籃球" "游泳"
do
echo $hobby
break
done
echo "你的愛好是:${hobby}"
演示2
#!/bin/bash
echo "你的愛好是什麼"
select hobby in "程式設計" "遊戲" "籃球" "游泳"
do
case $hobby in
"程式設計")
echo "程式設計,多敲程式碼"
break
;;
"遊戲")
echo "少玩遊戲"
break
;;
"籃球"|"游泳")
echo "運動有利健康"
break
;;
*)
echo "輸入錯誤,請重新輸入"
esac
done
3.Shell函式
函式分類
- 系統函式
- 自定義函式
3.1 系統函式
Shell程式設計和其他程式語言一樣, 有函式, 函式是由若干條shell命令組成的語句塊,實現Shell指令碼程式碼重用和模組化程式設計。
系統自帶提供的函式, 可以直接使用.
basename系統函式
basename函式用於獲取檔名的函式, 根據給出的檔案路徑截取出檔名
語法
basename [string / pathname] [suffix]
根據根據指定字串或路徑名進行擷取檔名, 比如: 根據路徑"/one/two/aa.txt", 可以截取出aa.txt
suffix: 用於擷取的時候去掉指定的字尾名.
演示
abc@aliyun:/tmp$ basename ./aa.sh # 獲取指定路徑的檔名
aa.sh
abc@aliyun:/tmp$ basename ./aa.sh .sh # 獲取檔名並去掉指定字尾
aa
dirname系統函式
從指定的檔案絕對路徑, 去除檔名,返回剩下的字首目錄路徑
dirname 檔案絕對路徑
3.2 自定義函式
開發人員可以通過自定義開發函式,實現程式碼重用.
# 函式的定義
[ function ] funname ()
{
命令
[return 返回值]
}
# 呼叫函式
funname 傳遞引數1 傳遞引數2 ...
可以帶function fun() 定義,也可以直接fun() 定義,不帶任何引數。
引數返回,可以顯示加:return 返回,如果不加,將以最後一條命令執行結果,作為返回值。 return後跟數值n(0~255)
注意
必須在呼叫函式地方之前,先宣告函式,shell指令碼是逐行執行, 只要先運行了函式, 後面才可以時使用函式
示例:無參無返回值函式
檔案指令碼程式碼
#!/bin/bash
demo()
{
echo "執行了函式"
}
# 呼叫函式
demo
示例:無參有返回值函式
#!/bin/bash
sum()
{
echo "求兩個數的和..."
read -p "輸入第一個數字: " n1
read -p "輸入第二個數字: " n2
echo "兩個數字分別為 $n1 和 $n2 "
return $(($n1+$n2))
}
# 呼叫函式
sum
echo "兩個數字的和為: $? " # 獲取函式返回值
示例:有參函式
在Shell中,呼叫函式時可以向其傳遞引數。在函式體內部,通過 $n
的形式來獲取引數的值,例如,$1
表示第一個引數,$2
表示第二個引數...
其他引數介紹
引數處理 | 說明 |
---|---|
$# | 傳遞到指令碼或函式的引數個數 |
$* | 以一個單字串顯示所有向指令碼傳遞的引數 |
$$ | 指令碼執行的當前程序ID號 |
$! | 後臺執行的最後一個程序的ID號 |
$@ | 與$*相同,但是使用時加引號,並在引號中返回每個引數。 |
$? | 顯示最後命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤。 |
演示
#!/bin/bash
funParam(){
echo "第一個引數為 $1 !"
echo "第二個引數為 $2 !"
echo "第十個引數為 $10 !"
echo "第十個引數為 ${10} !"
echo "第十一個引數為 ${11} !"
echo "引數總數有 $# 個!"
echo "作為一個字串輸出所有引數 $* !"
}
# 呼叫函式
funParam 1 2 3 4 5 6 7 8 9 10 22
Shell程式與函式的區別
函式和shell程式比較相似,區別在於:
Shell 程式(內建命令和外部指令碼檔案), 外部指令碼檔案是在子Shell中執行, 會開啟獨立的程序執行
Shell函式在當前Shell的程序中執行
演示
#!/bin/bash
demo(){
echo "函式中列印當前程序ID:$$"
}
echo "當前指令碼檔案(Shell程式)列印當前程序ID:$$"
# 呼叫函式
demo
4.Shell重定向輸入輸出
4.1 重定向介紹
標準輸入介紹
從鍵盤讀取使用者輸入的資料,然後再把資料拿到Shell程式中使用;
標準輸出介紹
Shell程式產生的資料,這些資料一般都是呈現到顯示器上供使用者瀏覽檢視;
預設輸入輸出檔案
每個 Unix/Linux 命令執行時都會開啟三個檔案, 檔案如下
檔名 | 型別 | 檔案描述符(file description, fd) | 功能 |
---|---|---|---|
stdin | (standard input) 標準輸入檔案 |
0 | 獲取鍵盤的輸入資料 |
stdout | (standard output) 標準輸出檔案 |
1 | 將正確資料輸出到顯示器上 |
stderr | (standard error) 標準錯誤輸出檔案 |
2 | 將錯誤資訊輸出到顯示器上 |
每個檔案都有一個唯一的 檔案描述符fd, 後面會通過唯一 檔案描述符fd 操作對應的資訊
Shell程式操作輸入輸出時用到這3個檔案
- Shell程式預設會從stdin檔案中讀取輸入資料
- Shell程式預設會向stdout檔案輸出正確資料
- Shell程式預設會項stderr檔案中輸出錯誤資訊
這3個檔案用於臨時傳輸資料使用
重定向輸入輸出介紹
-
標準輸入是資料預設從鍵盤流向程式,如果改變了它的方向,資料就從其它地方流入,這就是輸入重定向。
-
標準輸出是資料預設從程式流向顯示器,如果改變了它的方向,資料就流向其它地方,這就是輸出重定向。
Linux Shell 重定向分為兩種,一種輸入重定向,一種是輸出重定向;
重定向的作用
輸出重定向是指命令的結果不再輸出到顯示器上,而是輸出到其它地方,一般是檔案中。這樣做的最大好處就是把命令的結果儲存起來,當我們需要的時候可以隨時查詢。
重定向語法
命令 | 說明 |
---|---|
命令 > file | 將正確資料重定向輸出到 file 檔案中, 覆蓋方式 |
命令 < file | 將輸入重定向從 file 檔案中讀取資料 |
命令 >> file | 將正確資料重定向輸出到 file 檔案中, 追加方式 |
命令 < file1 > file2 | 從file檔案讀取資料, 輸出資料到file2檔案中 |
命令 fd> file | 根據指定的檔案描述符fd 將資料重定向輸出到 file 檔案中, 覆蓋方式 |
命令 fd>> file | 根據指定的檔案描述符fd 將資料重定向輸出到 file 檔案中, 追加方式 |
命令 > file fd1>& fd2 | 將 fd1 和 fd2 檔案描述符合並 輸出到檔案。 |
fd1<& fd2 | 將 fd1 和 fd2 檔案描述符合並 從檔案讀取輸入. |
<< tag | 讀取終端輸入資料, 將開始標記 tag 和結束標記 tag 之間的內容作為輸入。 標記名tag可以任意 |
在輸出重定向中,
>
代表的是覆蓋輸出,>>
代表的是追加輸出。fd是檔案描述符
0 通常是標準輸入(STDIN),
1 是標準輸出(STDOUT),
2 是標準錯誤輸出(STDERR)。
fd> 或 fd>> 中間不可以有空格
4.2 輸出輸入示例
輸出示例:正確資訊重定向輸出
建立檔案redirect1.txt
touch redirect1.txt
執行who命令重定向輸出到redirect1.txt檔案中
echo "itheima" >> redirect1.txt
輸出示例:錯誤資訊重定向輸出
預覽錯誤訊息
abc@aliyun:/tmp$ ls java
ls: cannot access 'java': No such file or directory
沒有java目錄所以報錯
將錯誤訊息輸出到error.log檔案中
ls java 2> redirect2.txt
2 是標準錯誤輸出(STDERR), 注意
>
覆蓋方式輸出
2>
注意fd與>符號之間不能有空格
輸出示例:正確和錯誤資訊同時輸出
將正確資訊與錯誤資訊都儲存到一個檔案中
echo "itcast" > redirect2.txt 2>&1
數字 1 代表正確輸出的結果輸出到檔案中
數字 2 代表錯誤結果輸出到檔案中
2>& 1
將正確和錯誤都輸出到檔案中.2>&
中間不能有空格, 寫法有2種 合併第一種寫法:
2>& 1
合併第二種寫法:
2>&1
執行效果
abc@aliyun:/tmp$ echo "hahaha" > loggg.txt 2>&1
abc@aliyun:/tmp$ cat loggg.txt
hahaha
abc@aliyun:/tmp$ ls java >> loggg.txt 2>&1
abc@aliyun:/tmp$ cat loggg.txt
hahaha
ls: cannot access 'java': No such file or directory
輸入示例:統計檔案資料行數
Linux wc 命令可以用來對文字進行統計,包括單詞個數、行數、位元組數
wc [options] [檔名]
options有如下:
選項 | 含義 |
---|---|
-c |
character, 統計位元組數 |
-w |
word, 統計單詞數 |
-l |
line, 統計行數 |
演示
統計檔案redirect2.txt中資料行數
wc -l < redirect2.txt
執行效果
abc@aliyun:/tmp$ wc -l < loggg.txt
2
輸入示例:逐行讀取檔案資料
迴圈讀取檔案每一行資料
while read str; do echo $str; done < redirect2.txt
執行效果
abc@aliyun:/tmp$ while read str;do echo $str;done < loggg.txt
hahaha
ls: cannot access 'java': No such file or directory
輸入示例:讀取終端輸入資料的行數
abc@aliyun:/tmp$ wc -l <<END
> aa
> bb
> cc
3
abc@aliyun:/tmp$