前言:程序員
問題一:什麼是shell?shell
答:從程序員的角度來看, Shell自己是一種用C語言編寫的程序,從用戶的角度來看,Shell是用戶與Linux操做系統溝通的橋樑。用戶既能夠輸入命令執行,又能夠利用 Shell腳本編程,完成更加複雜的操做。在Linux GUI日益完善的今天,在系統管理等領域,Shell編程仍然起着不可忽視的做用。深刻地瞭解和熟練地掌握Shell編程,是每個Linux用戶的必修功課之一。編程
目前最流行的Shell稱爲bash Shell,bash Shell腳本編程以其簡潔、高效而著稱,多年來成爲Linux程序員和系統管理員解決實際問題的利器。vim
問題2、爲何要使用shell腳本?bash
答:使用腳本編程語言的好處是,它們多半運行在比編譯型語言還高的層級,可以輕易處理文件與目錄之類的對象。之因此要使用shell腳本是基於:編程語言
簡單性:shell是一個高級語言,經過它,你能夠簡潔地表達複雜的操做。編輯器
可移植性:使用POSIX所定義的功能,能夠作到腳本無須修改就能夠在不一樣的系統上執行。ide
開發容易:能夠在短期內完成一個功能強大有好用的腳本。函數
1、初識shell腳本編程
測試
利用vim文本編輯器編寫Shell腳本的格式是固定的,以下:
#!/bin/bash
#This is a shell file
echo "Hello World!"
第一行必定要使用#!指明系統須要哪一種shell解釋用戶的shell程序,如:#!/bin/sh,#!/bin/bash,#!/bin/csh,#!/bin/tcsh和#!/bin/ksh等。若是首行沒有這句話,在執行腳本文件的時候,將會出現錯誤。
除首行外,以#開頭的行就是註釋行。
後續的部分就是主程序,Shell腳本像高級語言同樣,也有變量賦值,也有控制語句。
一般shell腳本多以.sh爲後綴。
執行shell的方式有兩種:第一種是爲shell腳本加上可執行權限並執行,第二種是經過bash命令執行shell腳本。
2、shell的基本語法知識
一、變量類別
(1)本地變量:只對當前shell進程有效的變量;對其它shell進程無效,包當前shell進程的子進程;
VAR_NAME=VALUE
變量賦值:向變量的存儲空間保存數據
變量引用:${VAR_NAME}
"":弱引用,裏面的變量會被替換;
'':強引用,裏面的全部字符都是字面量,直接輸出;
(2)環境變量:對當前shell進程及其子shell有效,對其它的shell進程無效;
定義:export VAR_NAME=VALUE
導出:export VAR_NAME
(當定義了一個本地變量,要在當前shell的子shell進程中使用,可用導出: export VAR_NAME)
撤消變量:unset VAR_NAME(可撤銷本地變量和環境變量)
設置只讀變量:readonly VAR_NAME(標誌變量爲不可改變的,即只讀變量)
(3)局部變量:對shell腳本中某代碼片段有效;一般用於函數本地;
local VAR_NAME=VALUE(當函數調用結束,局部變量會隨之消失。也能用unset 撤銷局部變量。)
(4)位置變量:
$1, $2, ..., ${10}(當兩位數或超過兩位數時,最好用{}括起來)
(5)特殊變量:
$#: 傳遞到腳本的參數個數
$*: 以一個單字符串顯示全部向腳本傳遞的參數
$$: 腳本運行的當前進程ID號
$!: 後臺運行的最後一個進程的進程ID號
$@: 與$*相同,可是使用時加引號,並在引號中返回每一個參數
$-: 顯示shell使用的當前選項,與set命令功能相同
$?: 顯示最後命令的退出狀態,0表示成功,其餘任何值都表示有錯誤
2、變量賦值
變量=值
任何變量無需事先聲明,可直接使用
值默認都是字符型
例如:a=abc, b=3
a=3(不能寫成 a = 3 ,即中間不能有空格。因在bash中是基於命令行的,中間有空格,bash會把其後的 = 和 3 看作選項或參數)
賦值:
a=4
加強型賦值:
+=, -=, *=, /=, %=
a=$[$a+1] 至關於 let a+=1 (let a+=1至關於let a=$a+1)
自加:var++, var--, ++var, --var
三、算術運算
(1)如何定義整型變量:
let VAR_NAME=INTEGER_VALUE
例如:let a=3
declare -i VAR_NAME=INTEGER_VALUE
例如:declare -i a=3
注意:即便沒有定義爲整型變量,字符型的數字依然能夠參與算術運算;bash會執行變量類型的隱式類型轉換;
(2)實現算術運算的方式:
let VAR_NAME=ARITHMATIC_EXPRESSION
( 使用let進行算術運算,要使用結果,必須把運算結果存儲在變量中,再去引用變量(不可用` `引用該命令的執行結果) )
VAR_NAME=$[ARITHMATIC_EXRESSION]
(不是命令,而是表達式)
VAR_NAME=$((EXPRESSION))
(不是命令,而是表達式)
VAR_NAME=$(expr $num1 + $num2)
(使用expr進行算術運算,可用` `引用該命令的執行結果)
(3)算術運算符:
+ :加
- :減
* :乘
/ :除
%:取模,取餘數
**: 次方,如: 2**2
四、條件測試
命令執行成功與否即爲條件測試
test EXPR
[ EXPR ]
[[ EXPR ]]
比較運算:
>, <, >=, <=, ==, !=
(1)測試類型:根據比較時的操做數的類型
整型測試:整數比較
字符測試:字符串比較
文件測試:判斷文件的存在性及屬性等
注意:比較運算一般只在同一種類型間進行
(2)整型測試:
-gt: 大於,例如 [ $num1 -gt $num2 ]
-lt: 小於
-ge: 大於等於
-le: 小於等於
-eq: 等於
-nq: 不等於
(3)字符串測試:
雙目
> 大於,例如[[ "$str1" > "$str2" ]]
< 小於
>= 大於等於
<= 小於等於
== 等於
!= 不等於
單目:
-n String: 是否不空,不空則爲真,空則爲假
-z String: 是否爲空,空則爲真,不空則假
字串測試中的模式匹配:
[[ "$var" =~ PATTERN ]]
(4)文件測試:
-a FILE :存在爲真,不然爲假;
-e FILE: 存在則爲真;不然爲假;
-f FILE: 存在而且爲普通文件,則爲真;不然爲假;
-d FILE: 存在而且爲目錄文件,則爲真;不然爲假;
-L/-h FILE: 存在而且爲符號連接文件,則爲真;不然爲假;
-b: 塊設備
-c: 字符設備
-S: 套接字文件
-p: 命名管道
-s FILE: 存在而且爲非空文件則爲值,不然爲假;
-r FILE :是否可讀
-w FILE :是否可寫
-x FILE :是否可執行
file1 -nt file2: file1的mtime新於file2則爲真,不然爲假;
file1 -ot file2:file1的mtime舊於file2則爲真,不然爲假;
五、if語句
(1)單分支的if語句: if 測試條件; then 選擇分支 fi 表示條件測試狀態返回值爲0時,則執行選擇分支 或者另一種格式: if 測試條件 then 選擇分支 fi (2)雙分支的if語句: if 測試條件; then 選擇分支1 else 選擇分支2 fi 兩個分支僅執行其中之一。 (3)多分支的if語句: if 條件1; then 分支1 elif 條件2; then 分支2 elif 條件3; then 分支3 ... else 分支n fi
五、case語句
case 語句:有多個測試條件時,case語句會使得語法結構更明晰 格式: case 變量引用 in PATTERN1) 分支1 ;; PATTERN2) 分支2 ;; ... *) 分支n ;; esac PATTERN:類同於文件名通配機制,但支持使用|表示或者; a|b: a或者b *:匹配任意長度的任意字符 ?: 匹配任意單個字符 []: 指定範圍內的任意單個字符 (區分字母大小寫) t-size:14px; font-family:'宋體'; " >**: 2**2 (分支後的「;;」表示分支結束,再也不往下執行,至關於Java中的switch 中的break。若是進入分支1,不加「;;」,則會繼續往下執行。) (注意:在bash編程中,case的分支中必須加上「;;」,若是不加「;;」或僅加了「;」,會有語法錯誤!!!)
六、for語句
格式: for VAR_NAME in LIST do 循環體 done 或者能夠寫成: for VAR_NAME in LIST ;do 循環體 done LIST:列表,中間包括一個或多個元素 退出條件:遍歷結束 for的第二種使用格式 : for ((初始條件;測試條件;修改表達式)); do 循環體 done
七、while語句
while 測試條件; do 循環體 done 如測試結果爲「真」,則進入循環;退出條件爲,測試條件爲假;
八、until語句
until 測試條件; do 循環體 done 若是測試結果爲「假」,則進入循環;退出條件爲,測試條件爲真;
九、函數
(函數要先定義,而後才能使用)
語法: 兩種格式: function F_NAME { 函數體 } F_NAME() { 函數體 }
可調用:使用函數名
函數名出現的地方,會被自動替換爲函數;
函數中的變量:
(1)本地變量:做用域爲整個bash進程
varname=value
(2)局部變量:做用域只對當前代碼段有效(只在函數中有效)
local varname=value (使用local關鍵字定義)
(3)環境變量:做用域爲當前shell進程及其子進程
export varname=value
函數的返回值:
函數的執行結果返回值:代碼的輸出
函數中的打印語句:echo, print
函數中調用的系統命令執行後返回的結果
執行狀態返回值:
函數體中最後一次執行的命令狀態結果
自定函數執行狀態的返回值:return #
函數能夠接受參數:
在函數體中調用函數參數的方式同腳本中調用腳本參數的方式:位置參數
$1, $2, ...
$# :參數個數
$*, $@ :取全部參數