shell指令碼總結
shell總結
shell指令碼的本質是shell命令的有序集合
建立shell指令碼的步驟:建立shell指令碼,編寫任意多行作業系統命令或shell命令,增加檔案的執行許可權,結束
shell變數
shell允許使用者建立變數儲存資料,但不支援資料型別。將任何賦給變數的值都解釋為一串字元
shell有如下四種變數:使用者自定義變數,位置變數,預定義變數,環境變數
使用者自定義變數:
定義變數:COUNT=1
使用時前面加$:echo $COUNT
刪除變數的賦值:unset COUNT
位置變數:
$0 與鍵入的命令列一樣,包含指令碼檔名
$1,$2...$9 分別包含第一個到第九個命令列引數
$# 包含命令列引數的個數
[email protected] 包含所有命令列引數:“$1,$2...$9 ”
$? 包含前一個命令的退出狀態
$* 包含所有命令列引數:“$1,$2...$9 ”
$$ 包含正在執行程序的ID號
shell環境變數
CDPATH 用於cd命令的查詢路徑
HOME 使用者主目錄
PATH 路徑
shell 程式和語句
shell程式由0到n條shell語句構成,shell語句包括三大類:功能性語句、結構性語句、說明性語句
說明性語句:以#開始的部分,不被解釋執行
可以出現在程式的任意位置,可以單獨一行,也可以接在執行語句的後面
功能性語句
read 從標準輸入讀出一行,賦給後面的變數
read var #把讀入的資料全部賦給var
read var1 var2 var3 #把讀入一行的第一、二個詞分別賦給var1、var2,其他的都賦給var3
如果執行read語句時標準輸入無資料,則程式在此停留等候,直到資料到來或終止執行
expr 主要用於簡單的整數運算,包括 + - \* / % 等
反撇號用於引用命令的執行結果
test 用於測試三種物件:字串、整數、檔案屬性
可用[ ]代替,注意左右都至少一個空格
如:test “$answer” = “
test $num -eq 18 #變數num的值是否為整數18
test -d tmp #測試tmp是否為一個目錄名
結構性語句:條件測試語句、多路分支語句、迴圈語句、迴圈控制語句、後臺執行語句
條件測試語句
if...then...else...fi
語法結構:
if 表示式
then
命令表1 #一條或者若干條命令
else
命令表2 #一條或者若干條命令
fi
如果表示式為真,執行命令表1,否則執行命令表2
例子;
if [ -f S1 ] #測試引數是否為檔案
then
echo “File $1 exists”
fi
if [-d $HOME/$1] #測試引數是否為目錄
then
echo “File $1 is a directory”
fi
多路分支語句
case...esac
語法結構:
case 字串變數 in #case語句只能檢測字串變數
模式1)
命令表1
;;
模式2)
命令表2
;;
。。。。
*) # *表示其他所有
命令表n
;;
esac
例如:
case $1 in
file1)
echo “file1”
;;
file2)
echo “file2”
;;
*)
echo “others”
;;
esac
迴圈語句
for...do...done
當迴圈次數已知或者確定時,使用for迴圈語句來多次執行一條或一組命令,迴圈體由do和done來限定
for 變數名 in 單詞表
do
命令表
done
說明:變數依次取單詞表中的各個單詞,每取依次單詞,就執行一次迴圈體,迴圈次數為單詞表中的單詞個數,命令表中可以是一條或由分號隔開的多條命令
如果單詞表是命令列上的所有位置引數時,可以省去 in 單詞表
list=`ls`
for file in $list
do
if[ $1 = $file ]
then
echo “$file found”;
exit; #退出shell指令碼
fi
done
while...do...done
語法結構:
while 命令或表示式
do
命令表
done
說明:while首先測試其後的命令或表示式的值,如果為真,就執行一次迴圈體中的命令,然後再測試該命令或表示式的值,執行迴圈體,知道為假,退出迴圈
until...do...done
語法結構:
until 命令或表示式
do
命令表
done
與上面的相反
迴圈控制語句:
break 和 continue
break n 跳出n層
continue 馬上跳轉到最近一層迴圈的下一輪迴圈
continue n 轉到最近n層迴圈語句的下一輪迴圈上
shell函式
shell程式中,常把完成固定功能且多次使用的一組命令封裝在一個函式中,每當要使用時,呼叫函式名即可
函式呼叫前必須先定義,即順序上先定義函式,再呼叫
呼叫程式可以傳遞引數給函式,函式可以用return語句把執行結果返回呼叫程式
函式只在當前shell中起作用,不能輸出到子shell中
shell函式定義格式
function funtion_name () #function可以省掉
{
...
}
函式呼叫方式
value_name = `function_name [arg1 arg2 ...]` #函式結果返回給變數
或
function_name [arg1 arg2 ...]
echo $? #獲取函式返回的狀態
函式變數的作用域
全域性作用域:在指令碼的其他地方都可以訪問該變數
區域性作用域:只能在宣告的作用域內訪問
區域性變數的宣告: Local variable_name = value
指令碼除錯:
跟蹤指令碼執行結果:
在希望開始除錯的地方插入 set -x
在希望結束除錯的地方插入 set +x
---------------------------------------------------------------------
---------------------------------------------------------------------
Bash shell結構
1:shbang行:指令碼的第一行,告之核心用哪個shell解釋shell指令碼,由#!加shell的完整路徑組成
2:註釋:#後面的為註釋,可以在一行後
3:shell萬用字元或元字元:shell中字元意義比較特殊,如* ? [] > < 2> >> |等,防止這些字元被解釋,則必須引用他們
4:區域性變數:區域性變數作用域在本shell中
5:全域性變數:又稱為環境變數,由內建的export命令建立,作用域在本shell及子shell中
6:提取變數值:$
7:引數:可以從命令列傳遞引數給指令碼
8:命令替換:`A` $(A) 結果可以賦給一個變數或代替所在位置
---------------------------------------------------------------------
正則表示式
正則表示式是一種字元模式,在查詢過程中匹配指定的字元,可以用特殊的元字元來控制它們,正則表示式都被置於兩個正斜槓//之間
元字元:表達的是不同於字元本身的含義
本書中的元字元有兩類:shell元字元、正則表示式元字元,它們各司其職,shell元字元是由shell解析的,就是下面所講的檔名置換;正則表示式元字元是由各種執行模式操作的程式來解析的,如vi、grep、sed、awk
---------------------------------------------------------------------
正則表示式元字元:
^ 行首定位
$ 行尾定位
. 匹配單個字元
* 匹配0或多個重複的位於*前的字元
[] 匹配指定組字元中的任意一個 ;如[LlT]
[-] 匹配指定範圍內的字元 ;如[x-yA-Z0-8]
[^] 匹配不在指定組內的字元
[^ - ]跟上面的相反
\ 轉移跟在後面的字元 #轉義元字元,使之不被解釋
\< 詞首定位符 #定位以什麼開頭的詞
\> 詞尾定位符 #定位以什麼結尾的詞
---------------------------------------------------------------------
grep 家族
grep家族由grep、egrep、fgrep組成
grep命令在檔案中全域性查詢指定的正則表示式,並列印所有包含該表示式的行
一般格式:grep [選項] 基本正則表示式 [檔案]
選項:-n 顯示行號 -i 大小寫不敏感 -w表示式作為詞來查詢,也就是不是一個詞的一部分 -r 遞迴查詢
基本正則表示式:可為字串,如果為字串,最好用“”如果是模式匹配,用‘’呼叫變數時,也應該使用“”
檔案:可以為多個檔案;如 A1 A2
常用舉例子
grep -n “your” www #檔案www中查詢含有your單詞的行,且輸出行號
grep -nw “your” www #檔案www中查詢含以your做單詞的行,且輸出行號
grep -nr ‘[a-zA-Z0-9].you’ ./ #遞迴./ 中查詢含有以a-z A-Z 0-9開始的單詞的行,且輸出行號
---------------------------------------------------------------------
find命令及xargs
find pathname -options [-print -exec -ok]
常用的options為name 此時記住要用引號將檔名模式引起來
find ./ “*org.txt” #在當前目錄及子目錄中尋找以org.txt結尾的檔案
find 找到檔案後可用xargs對其操作
find ./ “*org.txt” | xargs ls
find ./ “*org.txt” | xargs grep “device” #在結果中搜索device
---------------------------------------------------------------------
啟動
系統啟動後
->init->getty程序
->/bin/login 初始化環境,啟動shell
->/bin/bash 執行/ect/profile,執行~/.bash_profile ~/.bash_login ~/.profile,執行~/.bashrc
->等待使用者輸入
---------------------------------------------------------------------
環境
一個程序的環境包括:變數等,它定義了可以從一個程序繼承到下一個程序的特性
使用者的shell配置定義在shell初始化檔案中,bash shell有許多啟動檔案,這些檔案可以執行source命令,對一個檔案執行source命令會使得這個檔案中的所有設定稱為當前shell的一部分,也就是說不會建立子shell
登陸時,會執行~/.bash_profile檔案執行source命令,如無,則source ~/.bash_login,若無,則source ~/.profile,這三個檔案只能source一個,再source ~/.bashrc
~/.bashrc:包含特定的變數和別名,當一個新的bash shell啟動或bash指令碼啟動時會自動執行source ~/.bashrc
在當前提示符下輸入shell或bash啟動的是子shell
/etc/bashrc:系統級的函式和別名可以在/etc/bashrc檔案中設定,主提示符一般在這設定
~/.profile:是一個使用者定義的初始化檔案,它是被Bourne shell使用的,因此不能包括對bash shell的特定設定,執行bash時只有沒找到其他檔案時才source此檔案,它允許使用者定製和修改shell環境,也可以放應用程式的初始化
---------------------------------------------------------------------
source命令或dot命令(.) 和 ./命令
source命令式內建的bash命令,來自C shell
dot命令也就是. 來自Bourne shell
二者完全一樣,都是一個指令碼名作為引數,shell將在當前的shell環境中執行這個指令碼,也就是不啟動子shell,指令碼中的設定的所有引數將成為當前shell環境的一部分。
./執行指令碼時是建立子shell,指令碼中的設定引數在指令碼退出後就無效了。
例子:在家目錄下的.bashrc中加入WANG=”ni hao”
然後. .bash.rc
此時執行內容為 echo “$WANG”的 指令碼
如用 ./sh.sh 則無輸出 #./執行時是在起一個子shell
如用source sh.sh或 . sh.sh則輸出ni hao #source是在本shell中執行
---------------------------------------------------------------------
bash shell元字元(萬用字元)
\ 按字面含義解釋後面的那個字元
& 在後臺處理的程序
; 分隔命令
$ 替換命令
* 匹配任意字元
? 匹配任意單個字元
[...] 匹配[]中的任意一個字元
[!...] 不匹配[]中!的任意一個字元
(cmds) 在子shell中執行命令
{cmds} 在當前shell中執行命令
---------------------------------------------------------------------
檔名置換
計算命令列時,shell會用元字元來縮寫能夠匹配某個特定字元組的檔名或路徑名
將元字元展開為檔名或路徑名的過程稱為檔名替換或globbing
* 匹配檔案(夾)名中的任意字串
如:ls app*
cd cmdd*
? 匹配檔案(夾)名中的任意一個字元
[...] 匹配[]中的任意一個字元
[!...] 不匹配[]中!的任意一個字元
如:ls [a-z]*.o #匹配以a-z開頭的已.o結尾的檔案
ls [!0-9]*.o #匹配以非0-9開頭的已.o結尾的檔案
---------------------------------------------------------------------
命令執行順序
命令1 && 命令2 #命令1執行成功才會執行命令2
命令1 || 命令2 #命令1執行不成功才會執行命令2
用() 和 {}將命令結合在一起
---------------------------------------------------------------------
Bash shell變數
變數可分為兩種:區域性變數和環境變數
區域性變數只在建立他們的shell中可用,環境變數作用域可以擴充套件到子shell中去
變數命名規則:可以是字母、0-9、下劃線組成,必須以字母或下劃線開頭,其他字元都標誌著變數名的終止,變數名大小寫敏感
有兩個內建命令可以用來建立變數,他們是declare、typset,其選項可以控制變數的設定方式,建議使用declare.
格式:declare [選項] 變數=值
選項:-x 將變數設定成環境變數
-r 將變數設定成只讀變數
-a 將變數當一個陣列
---------------------------------------------------------------------
建立區域性變數
1:變數賦值:變數=值 #注意等號周圍不能有任何空白字元,如果想賦空,可以在等號後跟上換行符
2:內建命令declare 變數=值 #注意等號周圍不能有任何空白字元,如果想賦空,可以在等號後跟上換行符
例子:
設定:round=world 或 round=”world nice” #“”保護空白符
設定:declare round=world
輸出:echo $round
設定:file.bak=”xxxx” 錯,變數名中出現非法字元
local函式:函式內建立區域性變數可以用local函式
---------------------------------------------------------------------
建立環境變數
環境變數,又被稱為全域性變數,作用域可以擴充套件到子shell中,通常環境變數用大寫
環境變數是已經用export內建命令匯出的變數,如果想設定環境變數,只需在設定變數時或賦值後使用export命令即可,declare 帶-x也是設定環境變數
設定環境變數:
1:export 變數=值 #注意等號周圍不能有任何空白字元,如果想賦空,可以在等號後跟上換行符
2:變數=值; export 變數 #注意等號周圍不能有任何空白字元,如果想賦空,可以在等號後跟上換行符
3:declare -x 變數=值 #注意等號周圍不能有任何空白字元,如果想賦空,可以在等號後跟上換行符
---------------------------------------------------------------------
設定只讀變數
只讀變數是不能被重新定義或復位的特殊變數,但是如果使用declare定義的變數,可以重定義,不能復位
設定:name=”TOM”
readonly name #設定只讀
unset name #不能復位
name=Jem #不能重定義
設定:declare -r city=”shanghai”
unset city #不能復位
declare city=“beijin” #可以
---------------------------------------------------------------------
提取變數的值
在變數前加$
---------------------------------------------------------------------
復位變數
只要不被設定只讀,區域性變數和環境變數都可以用unset命令復位
格式:unset 變數名
---------------------------------------------------------------------
顯示變數值
1:echo [選項] 變數 #echo將他的引數顯示到標準輸出上
選項:-e #允許解釋轉義字元,如echo -e “\a” \a轉義為報警
如:echo The name is $NAME
echo -e “\a” #報警
2:printf命令
---------------------------------------------------------------------
變數擴充套件修飾符
可以用一些專用修飾符來測試和修改變數,修飾符首先進行簡單的條件測試,檢查某變數是否已被設定,然後根據測試結果給變數賦值
${VA:-word} #如變數VA已經設定且非空,則代入其值,否則代入word 臨時替換預設值
${VA:=word} #如變數VA已經設定且非空,則代入其值,否則VA設定為word,代入VA永久替換預設值
${VA:+word} #如變數VA已經設定且非空,則代入word,否則代入空值 臨時替換預設值
${VA:?word} #如變數VA已經設定且非空,則代入其值,否則輸出word且從shell退出 基於預設值建立錯誤資訊
注:不加冒號時,值為空也被認為已經設定
如:echo ${name-Joe} #結果為空
echo ${name:-Joe} #結果為Joe
echo ${namex:?”namex is undefined”}
echo ${y?} #如果y未設定,否則輸出parameter null or not set
${VA:offset} #獲取變數VA值中位置從offset開始的字串
${VA:offset:length} #獲取變數VA值中位置從offset開始長度為length的字串 建立字串
如:var=notebook
echo ${var:0:4} #結果note
---------------------------------------------------------------------
子串的變數擴充套件
模式匹配變數用來在串首或串尾截掉串的一部分,常用語刪除路徑名的頭或尾
${變數%模式} #將變數值的尾部與模式進行最小匹配,並將匹配到的部分刪除
${變數%%模式} #將變數值的尾部與模式進行最大匹配,並將匹配到的部分刪除
${變數#模式} #將變數值的頭部與模式進行最小匹配,並將匹配到的部分刪除
${變數##模式} #將變數值的頭部與模式進行最大匹配,並將匹配到的部分刪除
${#變數} #替換為變數中的字元個數,如果是*或@ ,長度則是位置參量的個數
如:
pathname=”/usr/bin/local/bin”
echo ${pathname%/bin*} #結果/usr/bin/local/
echo ${pathname%%/bin*} #結果/usr
echo ${pathname#/usr} #結果/bin/local/bin
echo ${pathname##/usr} #結果bin
echo ${#pathname} #結果8
---------------------------------------------------------------------
位置參量
下面這組專用內建變數常稱為位置參量,通常被shell指令碼用來從命令列接受引數,或被函式用來儲存傳遞給它的引數
$0 #指當前shell指令碼的名稱
$1-$9 #代表第一個到第9個位置參量
${10} ${11} #第10、11個位置參量,不用$10,$11
$# 其值為位置參量的個數,不含$0
$* 其值為所有的位置參量
“$*” 其值為“$1 $2 $3”
“[email protected]” 其值為“$1”“$2”“$3”
位置引數可以用set命令來設定、重置或復位
set -- #清除所有的位置引數
---------------------------------------------------------------------
其他特殊變數
$ #當前shell的pid
_ #當前sh的選項設定
? #已執行的上一條命令的退出值
! #最後一個進入後臺的作用的pid
---------------------------------------------------------------------
引用
用來保護特殊的元字元不被解釋和禁止參量擴充套件
引用有三種方式:反斜槓、單引號、雙引號
需要引用的特殊元字元有:
;
&
()
{}
|
< >
空格 tab 換行符
$
* [] ?
1:單引號和雙引號必須成對出現
2:單引號保護特殊元字元免受解釋,雙引號也能,但雙引號允許處理變數替換字元$和命令替換字元``和\
3:雙引號可以保護單引號,單引號可以保護雙引號
4:如果有不匹配的引號,bash會出現次提示符
反斜槓:反斜槓用於引用(或轉義)單個字元,使其免受解釋。
單引號中的反斜槓不會被解釋
如果在雙引號中,反斜槓將保護$ ``和反斜槓免受解釋
單引號:成對出現,保護所有元字元不被解釋,列印雙引號就必須用雙引號將其括起來,或反斜槓轉義
雙引號:同單引號,但是允許進行變數替換$和命令替換``和\
簡言之:單引號中什麼都不被解釋。雙引號中$ `` \這三個會被解釋,如不想解釋用\轉義
注意:``同$()是一樣的,所以$(date)也會展開
---------------------------------------------------------------------
命令替換
命令替換的用處是將命令的輸出結果賦給一個變數或將命令的輸出結果代入命令所在位置
bash 允許使用兩種格式:`命令` 和 $(命令)
執行擴充套件時,bash先執行命令,然後返回命令的標準輸出,輸出結果末尾的換行符都將被刪除,如果不想刪除,可用“”括起,如:echo “$(cal)”
如:echo “this is `date +%H`” #this is 09
d=$(date) #d存放命令date的結果
`命令` \保留字面意思,除非後面跟$ ` \ 且``中$ \生效,可用\轉義之,``中再有``的話必須用\轉義
$(命令) 中的所有特殊字元都不會解釋
命令替換可以被巢狀,``必須使用\`轉義,如echo `basename \`pwd\` ` #其中轉義後的`pwd`也是當做命令替換的,如:$(basename $(pwd))
---------------------------------------------------------------------
陣列
bash 中可以建立一維陣列,陣列允許將一列詞放到一個變數名中,可以用內建命令declare -a建立,或直接給變數名一個下標來建立,如x[0]=5 索引值為從0開始的整數,陣列無上限,索引也不必是有序數<