目錄
2.3,使用 bash 計算器在shell腳本中進行浮點運算
一,什麼是sh和bash?
#!/bin/sh是#!/bin/bash的縮減版
Linux系統中的/bin/sh本是bash的符號鏈接,鑑於bash過於複雜,有人把bash從NetBSD移植到Linux並更名爲dash,並建議將/bin/sh指向它,以獲得更快的腳本執行速度。Dash Shell比Bash Shell小的多,符合POSIX標準。
二,shell的基本用法
2.1,變量
2.1.1,變量的賦值
變量名=值 #注意賦值語句兩邊不能有空格,等號右邊若有空格的話,需要加上引號(單引號或雙引號都可以)。shell中可以在變量名前加上$字符來取變量的值。
#!/bin/bash
name=zhiwen
age=23
address="Hubei Wuhan"
money='100$'
echo "$name $age in $address"
echo "I have $meney!"
exit 0
注:單引號與雙引號的用法,在單引號中,所有特殊字符都沒有特殊含義;在雙引號中,"$"、" ` "(反引號)、"\"有特殊含義,其餘的沒有特殊含義。至於反引號 " ` ",反引號中可以用來引用系統命令,其中的內容將會被優先執行,其功能與$(...)一樣。
2.2.2,變量的類型
shell中有四種類型的變量:用戶自定義變量,環境變量,位置參數變量和預定義變量。
1)用戶自定義變量:一般小寫字母來命名,在當前shell中生效,也就是“局部變量”,如上面的name,age
2)環境變量:通常用大寫字母做名字,環境變量可以在當前shell和這個shell的所有子shell中生效,如果環境變量寫入相應的配置文件(如/etc/profile)那麼這個環境變量就會在所有shell中生效。系統自帶的環境變量的名字不可更改,但值可以按需更改。用戶可以使用export命令中自己創建環境變量:
export 變量名=變量值 # 創建環境變量並賦值
#一些主要的系統環境變量如下:
$HOME 當前用戶的家目錄
$PATH 以冒號分隔的用來搜索命令的目錄列表,決定了 shell 將到哪些目錄中去尋找命令或程序
$PS1 命令提示符,通常是 $ 字符,也可以自行設置
$PS2 二級提示符,用來提示後續的輸入,通常是 > 字符
$IFS 輸入域分隔符。當 shell 讀取輸入時,它給出用來分隔單詞的一組字符,通常是空格、製表
符和換行符
$0 shell 腳本的名字
$# 傳遞給腳本的參數個數
$$ shell 腳本的進程號(PID),腳本程序通常會用它來生成一個唯一的臨時文件,如
/tmp/tmpfile_$$
3)位置參數變量
位置參數變量主要用來向腳本中傳遞參數或數據,變量名不能自定義,變量作用也是固定的,主要有以下幾種位置參數變量
位置參數變量 | 描述 |
$1 $2、....... | 腳本程序的參數,分別代表程序的第一個參數,第二個參數......程序第10個以上參數需要用大括號包含如 ${10} |
$* | 代表命令行中的所有參數。在一個變量中將所有參數列出,各參數之間用環境變量 IFS 中的第一個字符分隔開。 |
$@ | 和 $* 一樣,也包含了命令行中的所有參數,但是不使用 IFS 環境變量,即使 IFS 爲空,參數也是分開顯示的 |
注:$* 將所有的參數視爲一個整體,而 $@ 將所有的參數分別視爲單獨的個體。一般來說,採用 $@ 來訪問腳本程序的參數會比較好,不必擔心 IFS 所設置的分隔符爲空而導致各參數連在一起分不清楚。
4)預定義變量
預定義變量是在bash中已經定義好的變量,變量名不能自定義,變量作用也是固定的,實際上,位置變量也是預定義變量的一種,除了上面介紹的,這裏在介紹兩個:
預定義變量 | 描述 |
$? | 保存最後一次執行的命令的返回狀態。 如果$?的值爲0,表示上一個命令成功執行;如果值非0,表示上一個命令沒有成功執行。 |
$! | 用於保存後運行的最後一個進程的PID號 |
2.2,算術運算
shell的算術運算符與C語言裏的差不多,優先級與順序也相同。但是,由於shell中所有變量都是被看做字符串來存儲的,因此,要處理算術表達式,還需要使用一些特殊手段將數值型字符串換成相應的數值。
2.2.1,使用expr命令對算術表達式求值
#expr 命令將它的參數當做一個表達式來求值,可以用來進行數學運算。如下
#!/bin/bash
a=2
b=3
c=`expr $a + $b`
echo $c
exit 0
注:輸出結果爲5,使用expr命令的那一行,使用的是反引號``,反引號中的內容優先執行,所以這一行代碼的作用是將expr $a + $b這一表達式的執行結果賦給c。也可以使用$(...)來替代反引號:c=$(expr $a + $b)。反引號是一種比較老的語法形式,如果你希望自己寫的腳本具備非常好的可移植性,那麼可以使用反引號,新的腳本程序一般都使用 $(...) 來替代反引號了。
2.2.2,使用$((...))的方法對算術表達式求值
expr 雖然功能強大,在進行一些運算的時候,需要使用 \ 符來進行轉義,這對於閱讀代碼的人來說並不友好。另一方面,expr 命令執行起來其實很慢,因爲它需要調用一個新的 shell 來處理 expr 命令。好的一種做法是使用 $((...)) 擴展的方式。只需要將準備求值的表達式放在 $((...)) 的括號中即可進行簡單的算術求值。且,所有支持 $(( ... )) 的shell,都可以讓用戶在提供變量名稱時,無須前置 $ 符
#!/bin/bash
a=5;b=6
echo $(($a + $b)) #輸出11,在變量名前加上$,在shell中一般是取變量值的意思
echo $((a + b)) #輸出11,可見,變量前不加$也是可以的
echo $((a | b)) # 輸出 7 。這裏的 | 是按位或操作符
echo $((a || b)) # 輸出 1 。這裏的 || 是邏輯或操作符
echo $((a & b)) # 輸出 4 。這裏的 & 是按位與操作符
echo $((a && b)) # 輸出 1 。這裏的 && 是邏輯與操作符
echo $((a * b)) # 輸出 30
echo $((a == b)) # 輸出 0
exit 0
2.3,使用 bash 計算器在shell腳本中進行浮點運算
安裝bash 計算器 bc
#!/bin/bash
val1=$(echo "scale=4;5/4" | bc)
echo the value of val1 is $val1
注:輸出:the value of val1 is 1.2500
2.4,shell中的條件判斷命令test和[
test 命令與 [ 命令的作用其實是一樣的,使用 [ 命令的時候,一般在結尾加上 ] 符號,使代碼更具可讀性。在使用 [ 命令時,[ 符號與被檢查的語句之間應該留有空格。shell 中通常使用 test 命令來產生控制結構所需要的條件,根據 test 命令的退出碼決定是否需要執行後面的代碼。
2.4.1,字符串比較
str1="zhiwen"
str2="wenzi"
#用test命令,test語句的結果將作爲if的判斷條件,如果爲真即條件爲真,則執行if下面的語句
if test "$str1" = "$str2" ;then
....
fi
#用[命令的話,可以這樣,注意[與表達式之間要有空格
if [ "$str1" != "$str2" ] ; then
....
fi
#-n string,如果字符串不爲空則結果爲真
if [ -n "$str1" ] ; then
....
fi
#-z string,如果字符串爲空(null),則結果爲真
if [ -z "$str1" ] ; then
....
fi
注:使用字符串比較的時候,必須給變量加上引號 " " ,避免因爲空字符或字符串中的空格導致一些問題。實際上,對於條件測試語句裏的變量,都建議加上雙引號,能做字符串比較的時候,不要用數值比較。
2.4.2,算術比較
num1=2
num2=3
#expr1 -eq expr2 如果兩個表達式相等,則結果爲真
if [ "$num1" -eq "$num2" ] ; then
...
fi
#expr1 -ne expr2 如果兩個表達式不相等,則結果爲真
if [ "$num1" -ne "$num2" ] ; then
....
fi
#expr1 -gt expr2 如果 expr1 > expr2 ,則結果爲真
if [ "$num1" -gt "$num2" ] ; then
....
fi
#expr1 -ge expr2 如果 expr1 >= expr2 ,則結果爲真
#expr1 -lt expr2 如果 expr1 < expr2,則結果爲真
#expr1 -le expr2 如果 expr1 <= expr2,則結果爲真
#!expr 如果表達式爲假,則結果爲真
注:算術比較和字符串比較之間的不同之處,字符串比較比較的是兩個字符串,數字也是能組成字符串的,因此,當我們使用字符串比較的方式和數字比較的方式來比較兩串數字的時候,結果會有些不同。
#!/bin/bash
val1="1"
val2="001"
val3="1 " # 字符串 val3 在 1 的後面還有一個空格
[ "$val1" = "$val2" ]
echo $? # 使用字符串比較,退出碼爲 1,說明兩個字符串不相等
[ "$val1" -eq "$val2" ]
echo $? # 使用數值比較,退出碼爲 0,說明兩個數值相等
[ "$val1" = "$val3" ]
echo $? # 退出碼爲 1
[ "$val1" -eq "$val3" ]
echo $? # 退出碼爲 0
exit 0
注:如果在編寫代碼時,變量沒有加上雙引號,上述程序的結果又會不同,僅對 val3 進行取值,將會忽略該字符串中的空格,則第三個表達式的退出碼將爲 0 。這也說明了在變量兩邊加上雙引號的重要性。
2.4.3文件條件測試
文件條件測試 | 結果 |
-d file | 如果文件是一個目錄,則結果爲真 |
-e file | 如果文件存在,則結果爲真。注意,歷史上 -e 選項不可移植,所以通常使用的是 -f 選項 |
-f file | 如果文件存在且爲普通文件,則結果爲真 |
-g file | 如果文件的 set-group-id 位被設置,則結果爲真 |
-r file | 如果文件可讀,則結果爲真 |
-s file | 如果文件大小不爲 0 ,則結果爲真 |
-u file | 如果文件的 set-user-id 爲被設置,則結果爲真 |
-w file | 如果文件可寫,則結果爲真 |
-x file | 如果文件可執行,則結果爲真 |
#!/bin/bash
if [ -f /bin/bash ] ; then
echo "file /bin/bash exists"
fi
if [ -d /bin/bash ] ; then
echo "/bin/bash is a directory"
else
echo "/bin/bash is not a directory"
fi
exit 0
2.5,控制結構
shell 中的控制結構與其他程序設計語言中的控制結構類似,也是由順序結構、選擇結構和循環結構組成
2.5.1,if語句
if condition1
then
statements1
elif condition2
then
statements2
else
statements3
fi
2.5.2,case語句
case variable in
pattern [ | pattern ] ... ) statements;;
pattern [ | pattern ] ... ) statements;;
...
esac
#!/bin/bash
read -p "please keyin a word:" -t 5 word
case $word in
[a-z] | [A-Z] ) echo "You have keyin a letter";;
[1-9] ) echo "You have keyin a number";;
* ) echo "Unknow input"
esac
exit 0
2.5.3,for語句
shell 中的 for 語句與 C 語言等的 for 語句格式不一樣,但都是用來循環處理一組值的。這組值可以是任意字符串的集合(shell 在默認情況下所有變量都是以字符串的形式存儲的),它們可以在程序裏被列出,更常見的做法是使用 shell 的文件名擴展結果。 for 循環將會重複整個對象列表,依次執行每一個獨立對象的循環內容。對象可能是命令行參數、文件名或是任何可以以列表形式建立的東西。其語法如下:
for variable in values
do
statements
done
for 命令可以執行指定次數的一個或多個命令。在執行循環時,參數列表 values(可以有多個參數,如val1、val2、val3、...) 中的第一個參數將被賦給變量 variable,然後執行循環體(do 與 done 之間的命令);然後將列表中的第二個參數賦給 variable,依次循環,直到列表中的參數用完。舉個簡單的例子:
#!/bin/bash
for name in tongye wuhen xiaodong wufei laowang
do
echo $name
done
exit 0
2.5.4,while 與 until 語句
如果你需要進行循環操作而是先不知道需要循環的次數,可以使用 while 循環,while 循環的語法如下:
while condition
do
statements
done
until 循環語句的功能與 while 一樣,不同的是對於條件判斷結果的處理上。until 循環的語法如下:
until condition
do
statements
done
在 while 和 until 語句中,condition 是判斷條件,不同的是,while 語句中,若判斷條件爲真,則執行循環體;until 語句中,若判斷條件爲真,則停止執行循環體。
#!/bin/bash
i=1
while [ "$i" -le 10 ]
do
read -p "please keyin a number:" i
done
echo "$i"
exit 0
注: 這段代碼從鍵盤中輸入一個數字,直到輸入數值大於 10,退出循環並打印最後輸入的那個值。
歡迎訂閱公衆號【從零開始學無線】,一起學習交流!