菜鳥的Linux之路2 bash指令碼程式設計之一
shell指令碼程式設計
指令碼程式設計是一種程式設計能力的體現。
程式語言分為以下幾類:
1,機器語言
2,組合語言
3,高階語言:
(1)靜態語言:編譯型語言->強型別語言
強型別語言指的是變數的型別在程式執行前宣告好,不能在程式執行過程中隨意改變變數型別的語言。
強型別語言常見的有:C、C++、Java、C#等。
編譯型語言在程式執行前會依靠編譯器將程式全部轉換成可執行的二進位制格式。
編譯型語言需要事先確定好變數型別,因為它沒有直譯器,直譯器的機制可以幫助程式自動宣告變數的型別。
強型別的語言,變數在使用前必須進行宣告,甚至還要進行初始化。
數值初始化為0,字元初始化為空,0不是空,空是null->什麼都沒有。
(2)動態語言:解釋型語言->弱型別語言
弱型別語言指的是變數的型別不需要在程式執行前宣告,可以在程式執行的過程中根據需求改變變數的型別的語言。
弱型別語言常見的有:php、shell、python、perl等。
解釋型語言是邊解釋邊執行,執行特性成為on the fly。
解釋型語言需要一個直譯器,直譯器通常為靜態語言開發。
直譯器:
通常的講就相當於是人與計算機之間溝通的一個翻譯官。
使用直譯器還是編譯器是根據語言的型別來定的。
弱型別的語言變數在使用時宣告即可,甚至可以不區分型別,預設為字串。
弱型別的變數型別轉換分為顯式轉換和隱式轉換。
shell為弱型別的程式語言
高階語言也可以這麼分類:
(1)面向過程語言:shell指令碼、C語言等。
(2)面嚮物件語言:Java、Python、perl、C++等。
變數
->是一段被命名了的記憶體空間。
->記憶體是被編址了的儲存單元。
->變數一定是程序的變數,程序指的是執行中的程式。
變數型別:宣告變數的型別是為了事先確定好資料的儲存二進位制格式,和儲存長度。
變數型別分類:
1,字元型別
2,數值型別:
(1)整型
(2)浮點型:
浮點數就是小數,浮點數是分開存放的,小數點之前作為一個單位存放,小數點之後作為一個單位存放,然後再存放小數點的位置。
3,布林型(真假型):
邏輯型
邏輯運算:與、或、非、異或。
在邏輯運算中,1代表真,0代表假。
邏輯與運算:&&
邏輯或運算:||
邏輯非運算:!單目運算子,只需要一個運算元
計算機的內部是由邏輯閘電路組合起來的。
短路邏輯運算:
對於邏輯與運算來說,只要有一個為假,那麼結果一定為假(串聯關係)。
對於邏輯或運算來說,只要有一個為真,那麼結果一定為真(並聯關係)。
變數賦值
->VAR_NAME=value
變數溢位
->指的是使用者輸入資料的長度超過了所宣告變數型別的長度,導致資料溢位的現象。
->緩衝區溢位:由於使用者輸入資料的長度超過了變數型別的長度,導致資料溢位,溢位的資料恰巧控制了系統的管理程序。
->防止緩衝區溢位:在接收使用者輸入的資料之前,先在程式中判斷是否會導致溢位現象發生。
->有直譯器的語言,通常變數型別均為弱型別的,因為直譯器可以解決變數溢位的問題,這是程式本身的保護機制。
->但凡編譯型語言的變數型別均為強型別的,但是編譯器在編譯的時候也會幫我們檢查是否存在變數溢位的問題。
bash指令碼
變數命名規則
->只能包含字母、數字、下劃線,並且不能以數字開頭。
->不能和系統中已有的環境變數重名。
->最好做到見名知義。
變數型別
->環境變數:
作用域為當前shell程序或當前shell程序的子程序,只對當前shell有效。
環境變數的宣告:export VAR_NAME=value,export相當於是匯出的意思。
指令碼在執行的過程中會啟動當前shell的一個子shell程序,命令列中啟動的指令碼會繼承當前shell的環境變數,系統自動啟動的指令碼(非命令列啟動)就需要自我定義各種環境變數。
->本地變數(區域性變數是本地變數的子概念):
本地變數的宣告:
set命令:set(set可以省略) VAR_NAME=value
作用域為整個bash程序
區域性變數的宣告:
local VAR_NAME=value
作用域為當前程式碼段
->變數引用:
格式:${VAR_NAME}花括號可以省略,變數替換,變數引用。
‘’單引號強引用,語句段內的變數不做變數替換,輸出變數本身。
“”雙引號弱引用,語句段內的變數會進行變數替換。
->位置變數:
$1,$2,$3,...用來引用指令碼引數。
->特殊變數(系統變數):
是bash內建的,用來儲存某些特殊資料的變數。
$? 儲存上一個命令的執行狀態返回值,命令正確執行返回0,命令錯誤執行則返回1-255中的任意數字,針對255中錯誤型別。
命令執行之後可能有兩類返回值:
1,命令的執行結果。
2,命令的執行狀態返回值(0-255)
返回0值,表示命令是正確執行的
返回1-255的值,表示返回的是各種錯誤,1,2,127三個號碼是系統預留的,有特殊用途,其他代號可以使用者自定義。
->輸出重定向
> 重新定向到標準輸出,覆蓋原有內容。
>> 追加輸出,保留原有內容。
2> 重新定向到錯誤輸出。
2>> 追加錯誤輸出。
&> 重定向標準輸出和錯誤輸出到同一個文字,重定向所有。
/dev/null: 軟體裝置,bit bucket(位桶),也叫做資料黑洞,一般如果不想要命令的執行結果顯示到標準輸出上,那麼就在命令後面直接跟上重定向所有到/dev/null。
->撤銷變數
格式:unset VAR_NAME->不需要加$,因為撤銷的是變數而不是變數的值。
->檢視當前shell中的變數
set命令:用來檢視所有變數,包括環境變數和本地變數。
檢視環境變數:
printenv
env
export
特殊變數和位置變數無法檢視
shell預設是不能做算術運算的,預設所有變數的值都是字串。
指令碼
->其實就是命令的堆砌。
->按照實際需要,結合命令流程控制機制實現具體功能的源程式。
我們在編輯器中編寫好的程式只是一些二進位制ASICLL文字,而我們的linux核心卻只能識別ELF(可執行的、可連結的檔案格式)檔案,這時候我們就得需要需要一個shebang(指定程式的魔數),也就是我們常說的直譯器。
shebang
寫法:#!後面跟上直譯器指令碼的路徑,寫在指令碼中的第一行(指令碼中的第一行必須這麼寫,其後所有加#的行全為註釋行,不執行)。
練習:寫一個指令碼,要求:
1,新增5個使用者,zhubo1,zhubo2,zhubo3,zhubo4,zhubo5
2,每個使用者的密碼同用戶名,而且要求,新增密碼完成後,不顯示passwd命令的執行結果資訊
3,每個使用者新增完成後,都要顯示使用者某某已經成功新增
程式執行結果:
練習:寫一個指令碼,要求:
1,使用一個變數儲存一個使用者名稱
2,刪除此變數的使用者,且一併刪除其家目錄
3,顯示“使用者刪除完成”類的資訊
程式執行結果:
條件判斷
練習:寫一個指令碼,要求
1,給定一個使用者
2,如果使用者不存在,則新增該使用者,給密碼並顯示已新增成功
3,如果使用者存在,則顯示使用者已存在
指令碼執行結果:
練習:寫一個指令碼,要求
1,給定一個使用者
2,如果使用者存在,則顯示該使用者已存在
3,如果該使用者不存在,則新增該使用者,並給密碼並顯示已新增成功
指令碼執行結果:
bash中如何實現條件判斷:
條件測試型別:
1,整數測試:
整數比較(雙目操作):需要兩個運算元
->-eq(equal):測試兩個整數是否相等,比如$A -eq $B,測試AB中的值是否一樣,如果一樣則狀態返回值為0,等值比較。
->-ne(not equal):測試兩個整數是否不等,不等為真,等值為假。
->-gt(greater than):測試一個數是否大於另一個數,大於為真,否則為假。
->-lt(less than):測試一個數是否小於另一個數,小於為真,否則為假。
->-ge(greater equal):大於或等於。
->-le(less equal):小於或等於。
2,字元測試
3,文監測試:判斷檔案是否存在
條件測試的表示式:
1,[ expression ]
2,[[ expression ]]bash的關鍵字
3,test命令+expression
bash中命令間的邏輯關係:
邏輯與:&&
第一個條件為假時,第二個條件不用再判斷,最終結果已經有了。
第一個條件為真時,第二個條件必須得判斷。
邏輯或:||
! id xxx && useradd xxx &&之前為真時,才會執行&&之後的內容,否則&&之後的內容不會執行。
id xxx || useradd xxx ||之前為假時,才會執行||之後的內容,否則||之後的內容不會執行。
練習:寫一個指令碼,要求
1,新增三個使用者,但要先判斷使用者是否存在,不存在才能新增。
2,最後顯示當前系統上共有多少個使用者。
指令碼的執行結果:
練習:寫一個指令碼,要求
給定一個使用者:
1,如果其UID為0,就顯示此使用者為管理員。
2,否則,就顯示其為普通使用者。
指令碼執行結果:
條件判斷->控制結構:
->單分支的if語句(if...then寫一行時,then之前要加分號,不寫到一行的時候則不用加分號):
格式:if 判斷條件
then
expression1
expression2
...
fi
->雙分支的if語句
格式:if 判斷條件
then
expression1
expression2
...
else
expression1
expression2
...
fi
id xxx 是用來判斷使用者xxx是否存在的命令
if [ `id -u xxx` -eq 0 ]->利用的是命令的執行結果值0或者1。
if id xxx->利用的是命令的執行狀態返回值。
練習:
判斷當前系統上是否有使用者的的預設shell為bash
如果有,就顯示有多少個這類使用者;
否則,就顯示沒有這類使用者。
指令碼執行結果:
->引用命令的執行結果必須使用反單引號
練習:
判斷當前系統上是否有使用者的預設shell為bash
如果有,就顯示其中一個的使用者名稱
否則,就顯示沒有這類使用者
指令碼執行結果為:
練習:
給定一個使用者,判斷其UID和GID是否一樣
如果一樣,就顯示此使用者為"good guy";否則,就顯示此使用者為"bad guy"。
指令碼執行結果為:
如果不使用id命令,該如何獲得id號:
指令碼執行結果為:
shell中如何進行算術運算
A=3
B=6
1,let 算術運算表示式->let C=$A+$B
2,$[算術運算表示式]->$[C=$A+$B]
3,$((算術運算表示式))->$((C=$A+$B))
4,expr 算術運算表示式,表示式中各運算元及運算子之間要有空格,而且要使用命令引用
->expr C = $A + $B
練習:
判斷命令歷史中,歷史命令的總條目是否大於1000
如果大於,則顯示"some command will gone."
否則,顯示"OK."
指令碼執行結果: