1. 程式人生 > >linux的Shell指令碼程式設計

linux的Shell指令碼程式設計

Shell指令碼的建立與執行

在子Shell中執行
當執行一個指令碼檔案時,Shell就會產生一個子Shell(即一個子程序)去執行命令檔案中的命令。
1.將檔名作為Shell命令的引數:$bash script-file
2.現將指令碼檔案的許可權改為可執行,然後執行指令碼:$script-file

在當前Shell中執行
使用source 或 “ . ”命令執行,例如:$source script-file

Shell指令碼編碼規範
以#!開頭,指明使用何種Shell解析指令碼
例如:#!/bin/bash 或 #!/usr/bin/env bash

良好的編碼過飯還要求以註釋說明如下的內容:
#指令碼名稱
#指令碼功能
#作者及聯絡方式
#版本更新記錄
#版權宣告
#對演算法做簡要說明

Shell變數操作

變數替換

功能 表示式 說明
使用預設值 ${var:-word} 若var存在且非空,則值為$var;
若var未定義或為空值,則值為word,但var的值不變
賦予預設值 ${var:=word} 若var存在且非空,則值為$var;
若var未定義或為空值,則值為word,且var被賦值word
使用預設值 ${var:?word} 若var存在且非空,則值為$var;
若var未定義或為空值,則輸出word,並終止指令碼
使用預設值 ${var:+word} 若var存在且非空,則值為word;
若var未定義或為空值,則返回空值,但var的值不變

變數字串操作

表示式 說明
${#var} 返回字串變數var的長度
${var:m} 返回$var中從第m個字元到最後的部分
${var:m:len} 返回$var中從第m個字元開始,長度為len的部分
${var#pattern} 刪除${var}中開頭部分與pattern匹配的最小部分
${var##pattern} 刪除${var}中開頭部分與pattern匹配的最大部分
${var%pattern} 刪除${var}中結尾部分與pattern匹配的最小部分
${var%%pattern} 刪除${var}中結尾部分與pattern匹配的最小部分
${var/old/new} 用new替換${var}中第一次出現的old
${var//old/new} 用new替換${var}中所有的old
${var/#old/new} 用new替換${var}中開頭部分的old
${var/%old/new} 用new替換${var}中結尾部分的old

變數的數值計算

運算子 說明
+、-、*、/ 四則運算
**、% 冪運算、模運算
++、– 自增、自減
=、+=、-=、*=、/=、%= 賦值運算子
<、>、<=、>=、==、!= 比較運算
&&、||、! 邏輯運算

let命令,expr命令,以及最先出現的C語言風格的Shell算術運算子((…))
例如:$((a=2+3**2-1001%5))

Shell變數的輸入
read [-p ] <變數名>
讓使用者輸入,-p指定提示語句

Shell特殊變數

位置引數 說明
$0 指令碼名稱
$n n是大於等於1的正數,表示n個位置的引數。當n>9時,要使用${n} 形式引用
$# 位置引數的個數
[email protected]、“[email protected] 將每個位置引數看成單獨字串(以空格間隔)
$* 將所有位置引數看成一個字串(以空格間隔)
“$*” 將所有位置引數看成一個字串(以$IFS間隔)

Shell的程序狀態變數

特殊變數 說明
$$ 當前程序的PID
$! 執行在後臺的最後一個作業的PID
$? 在此之前執行的命令或指令碼的返回值,0表示成功,非0表示不同原因的失敗
$_ 在此之前執行的命令或指令碼的最後一個引數

注意:每個命令都會返回一個退出狀態碼(也稱為返回狀態),0為成功,非0為不成功,非零值通常都被解釋成一個錯誤碼,在指令碼中exit n命令將會把退出狀態碼(n)傳遞給父Shell(n必須是十進位制數,範圍是0~255)

Shell 指令碼跟蹤與除錯

使用bash引數除錯指令碼

命令 說明
bash -n < script name> 對指令碼進行語法檢查,通常在執行指令碼之前檢查其語法是否正確
bash -v < script name> 顯示指令碼中每個原始命令列及其執行結果
bash -x < script name> 以除錯模式執行指令碼,對指令碼中每條命令的處理過程:先執行替換,然後顯示,再執行命令

在指令碼中使用set命令除錯指令碼
當指令碼檔案較長時,可以使用set命令指定除錯一段指令碼。在指令碼中使用set -x命令開啟除錯模式,使用set +x命令關閉除錯模式,例如
#!/bin/bash
echo -e “Hello $LOGNAME, \c”
set -x ###開啟除錯模式
read -p “What is your name” name
echo “Hello $name”
set +x ###關閉除錯模式

條件測試和分支結構

測試語句
格式1: test <測試表達式>
格式2: [ <測試表達式> ]
格式3: [[ <測試表達式> ]]

測試語句可以判斷命令成功或失敗、表示式為真或假,bash中沒有布林型別,0表示成功或真,非零表示失敗或假。
注意:
1.格式1和格式2是等價的,格式3時擴充套件的test命令
2.在[[ ]]中可以使用Shell萬用字元進行模式匹配
3.&&,||,< 和>操作符能夠正常的在[[ ]]中使用,但不能再[ ]中出現
4.[和[[只後的字元必須是空格,]和]]之前必須是空格
5.要讀整數進行關係運算,可以使用Shell的算術運算子 (( ))進行測試

檔案測試運算子

操作符 說明
-e file 檔案是否存在
-f file 是否為普通檔案
-d file 是否為目錄
-L file 是否為符號連結檔案
-b file 是否為塊裝置檔案
-c file 是否為字元裝置檔案
-s file 檔案長度不為0
-r file 是否為只讀
-w file 是否為可寫
-x file 是否為可執行
-O file 測試者是否為檔案屬主
-G file 測試者是否為檔案同組人
-u file 是否為設定了SUID的檔案
-g file 是否為設定了SGID的檔案
-k file 是否為設定了黏貼位的檔案
file1 -nt file2 file1是否比file2新
file1 -ot file2 file1是否比file2舊
file1 -ef file2 file1是否與file2共用相同的i-node(連結)

字串測試操作符

操作符 說明
-z string 測試字串是否為空串
-n string 測試字串是否為非空串
string == string2 測試兩個字串是否相同
string != string2 測試兩個字串是否不相同

正數二元比較操作符

操作符功能 相等 不等 大於 大於等於 小於 小於等於
在[]中 -eq -ne -gt -ge -lt -le
在(( ))中 == != > >= < <=

使用邏輯操作符

操作符功能 “與”邏輯 “或邏輯” “非”邏輯
在[]中 -a -o -!
在(( ))中 && || !

分支結構迴圈

if語句

if < condition1>
then
	< commands1>
[ elif < condition2 >
then
	< command2 >
	..			]
[ else
	< commandn > ]
fi

注意:
1.elif語句塊可以有0到多個
2.else可以為0到1個
3.條件測試可以是表示式,
4.條件測試也可以是多個命令,以最後一個命令的退出狀態為其值
5.語句塊可以是一條命令、多條命令,也可以是空命令“ : ”(冒號,表示該命令不做任何事,只返回一個退出狀態0)
case語句

case expr in
	pattern1)
		commands1
		;;
	pattern2)
		commands2
		;;
	...
	*)
		commands
		;;
esac

注意:
1.表示式expr按順序匹配每個模式,一旦匹配成功,則執行該模式後的命令,然後退出case
2.如果沒有匹配到模式,則執行預設值“ *) ”後的命令
3.所有模式可以含有萬用字元和邏輯或“ | ”
4.除非特殊需要,否則每個命令塊左右必須有一個雙分號“ ;; ”,與C語言的switch中的break語句功能一致

while和until

while condition
do
	commands
done

當條件測試condition為真時執行迴圈體,否則退出迴圈

until  condition
do
	commands
done

當條件測試condition為真時結束迴圈,否則執行迴圈體

注意:bash提供了兩個迴圈控制語句
break:跳出迴圈
continue:跳出本次迴圈

for語句
foreach型迴圈

for variable in list
do
	commands
done

先將列表list的變數依次賦給variable執行commands,
C語言型迴圈

for (( exp1;exp2;exp3 ))
do
	commands
done

首先執行依次exp1(只執行一次),執行exp2,為真時,執行commands,在執行exp3,進入下一次迴圈,為假時退出迴圈,

seq語句與大括號表示式

語法 舉例 說明
seq n seq 10 生成序列[1…n],步長為1
seq m n seq 0 10 生成序列[m…n],步長為1
seq m s n seq 10 3 20 生成序列[m…n],步長為s
{m…n} {1…10}、{a…h}
{10…1}、{h…a}
生成序列[m…n]、[a…h],若m>n步長為1<br>生成序列[m…n]、[a…h],若m<n步長為-1
{m…n…s} {1…10…3}、{a…h…3}
{10…1…3}、{h…a…3}
生成序列[m…n]、[a…h],若m>n步長為s<br>生成序列[m…n]、[a…h],若m<n步長為-s

注意:
1.大括號表示式能生成字元序列,seq不能
2.大括號表示式能生成倒序,seq不能

select語句

select variable in list
do
	commands
done

與for的foreach類似,但是會在選單項之前新增一個從1開始的序號依次呈現給使用者,序號存在變數RELAY中。
注意:
1.list列表的選單項間隔符由環境變數IFS決定
2.按數值順序排列的選單會顯示到標準錯誤輸出
3.使用者直接按鍵將重新顯示選單
4.與for迴圈類似,省略in list時等價於in “$*”
5.select是個無限迴圈,通常要配合case語句處理不同的選單及退出。可以使用break退出迴圈,或exit終止指令碼

函式

函式定義

[function] name() {
	commands;
}

function可以省略
注意:函式和呼叫它的主檔案可以保持在同一個檔案中,函式定義必須出現在呼叫之前。
函式的執行方法
name 引數1 引數2 引數n
注意:
1.呼叫函式時,使用位置引數的形式傳遞引數
2.函式內的$1-$[n]、$*和[email protected]表示其接收的引數
3.函式呼叫結束後位置引數$1-$[n]、$*和[email protected]將被重置為呼叫函式之前的值
4.在主程式和函式中,$0始終代表指令碼名