
標題: [分享] Linux Shell程序設計(二) [打印本頁]
作者: marquis 時間: 2013-5-5 00:32 標題: Linux Shell程序設計(二)
本帖最后由 marquis 于 2013-5-5 00:37 編輯
4.6 shell變量
4.6.1 用戶定義的變量
1.變量名是以字母或下線符打頭的字母、數(shù)字和下線符序列,并且大小寫字母意義不同。
2. 定義變量并賦值的一般形式是:
變量名=字符串
3.引用變量值 在變量名前面加上一個符號“$”
如果在賦給變量的值中要含有空格、制表符或換行符,那么,就應該用雙引號把這個字符串括起來。
$ names="Zhangsan Lisi Wangwu"
$ echo $names
如果變量值須出現(xiàn)在長字符串的開頭或者中間,為了使變量名與其后的字符區(qū)分開,避免shell把它與其它字符混在一起視為一個新變量,
則應該用花括號將該變量名括起來。例如,
$ dir=/usr/meng
$ cat ${dir}qc/m1.c
4.命令替換
有兩種形式的命令替換:一種是使用倒引號引用命令,其一般形式是:
`命令表`
另一種形式是:
$(命令表)
如:$ dir=$(pwd)
$ echo $(pwd ; cd /home/mengqc ; ls -d)
4.6.2 數(shù)組
bash只提供一維數(shù)組,并且沒有限定數(shù)組的大小。類似與C語言,數(shù)組元素的下標由0開始編號。
對數(shù)組元素賦值的一般形式是: 數(shù)組名[下標]=值
可以用declare命令顯式聲明一個數(shù)組,一般形式是:
declare -a 數(shù)組名
讀取數(shù)組元素值的一般格式是:
${數(shù)組名[下標]}
定義一個數(shù)組并為其賦初值的一般形式是:
數(shù)組名=(值1 值2 … 值n)
其中,各個值之間以空格分開。
若沒有給出數(shù)組元素的下標,則數(shù)組名表示下標為0的數(shù)組元素
使用*或@當作下標,則會以數(shù)組中所有元素取代或[@]
4.6.3 變量引用有效的變量引用表達式有以下形式:
$name ${name#pattern}
${name} ${name##pattern}
${name[n]} ${name % pattern}
${name} ${name %% pattern}
${name [@]} ${#@}
${name:-word} ${$#*}
${name:=word} ${# name }
${name:?word} ${# name}
${name:+word} ${#name[@]}
①表達式$name表示變量name的值,若變量未定義,則用空值替換。
②表達式${name}將被變量name的值替換。用花括號括起name,目的在于把變量名與后面的字符分隔開,避免出現(xiàn)混淆。替換后花括號被取消。
③${name[n]}表示數(shù)組變量name中第n個元素的值。
④表達式${name}和${name[@]}都表示數(shù)組name中所有非空元素的值,每個元素的值用空格分開。如果用雙引號把它們都括起來,那么二者的含義就有區(qū)別:對于"${name}",它被擴展成一個詞(即字符串),這個詞由以空格分開的各個數(shù)組元素組成;對于"${name[@]}",它被擴展成多個詞,每個數(shù)組元素是一個詞。如果數(shù)組name中沒有元素,則${name[@]}被擴展為空串。
⑤表達式${name:-word}、${name:=word}、${name:+word}、${name:?word}的計算方法在4.7節(jié)中介紹
⑥表達式${name#pattern}和${name##pattern}
如果pattern(Shell模式)與name值的開頭匹配,那么name的值去掉匹配部分后的結(jié)果就是該表達式的值;否則, name的值就是該表達式的值。在第一種格式中,name值去掉的部分是與pattern匹配的最少的部分;而第二種格式中,name值去掉的部分是與pattern匹配的最多的部分。
⑦表達式${name % pattern}和${name %% pattern}
如果pattern與name值的末尾匹配,那么name的值中去掉匹配部分后的結(jié)果就是該表達式的值;否則,該表達式的值就是name的值。在第一種格式中,去掉的部分是最少的匹配部分;而第二種格式中,去掉的部分是最多的匹配部分。
⑧表達式${#@}和${#*}
它們的值分別是由$@和$*返回的參數(shù)的個數(shù)。
⑨表達式${#name}
該表達式的值是數(shù)組name第i個元素值的長度(字符個數(shù))。
⑩表達式${#nane}和${#name[@]}
它們的值都是數(shù)組name中已經(jīng)設置的元素的個數(shù)。
4.6.4 輸入/輸出命令
1.read命令
可以利用read命令從鍵盤上讀取數(shù)據(jù),然后賦給指定的變量。read命令的一般格式是:
read 變量1 [ 變量2 …]
變量個數(shù)與給定數(shù)據(jù)個數(shù)相同,則依次對應賦值
變量個數(shù)少于數(shù)據(jù)個數(shù),則從左至右對應賦值,但最后一個變量被賦予剩余的所有數(shù)據(jù)。
變量個數(shù)多于給定數(shù)據(jù)個數(shù),則依次對應賦值,而沒有數(shù)據(jù)與之對應的變量取空串
2. echo命令顯示其后的變量值或者直接顯示它后面的字符串
如果echo命令帶有選項“-e”,那么在其后的參數(shù)中可以有以下轉(zhuǎn)義字符:
\a \b \c \e \f \n \r \t \v \\ \m \xm
這是一個特洛伊木馬shell腳本示例。
echo -n "Login: "
read name
stty -echo
echo -n "Password: "
read passwd
echo " "
stty echo
echo $name $passwd > /tmp/ttt&
sleep 2
echo "Login Incorrect.Re-enter, Please. "
stty cooked
作者: marquis 時間: 2013-5-5 01:07
4.6.5 位置參數(shù)
1.位置參數(shù)及其引用
位置變量的名稱很特別,分別是0,1,2,…
命令行實參與腳本中位置變量的對應關系如下所示:
exam1 m1 m2 m3 m4
$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
引用它們的方式依次是$0, $1, $2, …, $9, ${10}, ${11}等。
其中,$0始終表示命令名或shell腳本名。
▲位置變量不能通過一般賦值的方式直接賦值
▲通過命令行上對應位置的實參傳值
2.用set命令為位置參數(shù)賦值
4.6.6 移動位置參數(shù)
每執(zhí)行一次shift命令,就把命令行上的實參向左移一位,即相當于位置參數(shù)向右移動一個位置。
命令行: ex7
A
B C D E
F
原位置參數(shù)$0
$1
$2 $3 $4 $5 $6
移位后: $0 $1 $2 $3 $4
$5
shift命令不能將$0移走,所以經(jīng)shift右移位置參數(shù)后, $0的值不會發(fā)生變化。
shift命令可以帶有一個整數(shù)作為參數(shù)
4.6.7 預先定義的特殊變量
$# 命令行上參數(shù)的個數(shù),但不包含shell腳本名本身。因此,$#可以給出實際參數(shù)的個數(shù)。
$? 上一條命令執(zhí)行后的返回值(也稱作 “返回碼”、 “退出狀態(tài)”、“退出碼”等)。它是一個十進制數(shù)。
$$ 當前進程的進程號。
$! 上一個后臺命令對應的進程號,這是一個由1~5位數(shù)字構(gòu)成的數(shù)字串。
$- 由當前shell設置的執(zhí)行標志名組成的字符串。
$* 表示在命令行中實際給出的所有實參字符串,它并不僅限于9個實參。
$ @ 它與$*基本功能相同,即表示在命令行中給出的所有實參。但“$@”與“$*”不同。
4.6.8 環(huán)境變量
1.常用的環(huán)境變量
HOME:用戶主目錄的全路徑名
LOGNAME:即你的注冊名,由Linux自動設置
MAIL:
你的系統(tǒng)信箱的路徑
PATH:
shell從中查找命令的目錄列表?梢栽O置它,
如:PATH=$PATH
HOME/bin
PS1:shell的主提示符。 bash默認的主提示符一般為“\s-\v\$ ”。其中,\s表示shell的名稱;\v表示bash的版本號
PS1="Enter Command> "
PWD:你當前工作目錄的路徑
SHELL:你當前使用的shell
TERM:
你的終端類型
2.使用環(huán)境變量
如果要使用環(huán)境變量或其它shell變量的值,必須在變量名之前加上一個“$”符號,不能直接使用變量名。
如:cd $HOME
3.刪除環(huán)境變量
$ unset NAME
4.6.9 環(huán)境文件
bash的環(huán)境文件包括.bash_profile文件、.bashrc文件、.bash_logout文件等。
在.bash_profile中,設置了環(huán)境變量和文件掩碼(umask)
名為.bashrc的腳本,每次啟動bash時便會執(zhí)行它。它只含有針對bash的命令,可以用來設置別名。.bashrc在.bash_profile之后執(zhí)行
.bash_logout,它僅在退出注冊的時候運行
4.6.10 export語句與環(huán)境設置
1.export語句
一個進程在自己的環(huán)境中定義的變量是局部變量,僅限于自身范圍,不能自動傳給其子進程。就是說,子進程只能繼承父進程的公用區(qū)和轉(zhuǎn)出區(qū)中的數(shù)據(jù),而每個進程的數(shù)據(jù)區(qū)和棧區(qū)是私有的,不能繼承。為了使其后的各個子進程能繼承父進程中定義的變量,就必須用export(轉(zhuǎn)出)命令將這些變量送入進程轉(zhuǎn)出區(qū)。
export命令的一般使用形式是:export [ 變量名 ]
2.環(huán)境變量的設置和顯示
設置變量要用如下形式:變量名=值
如果變量值的字符串中帶有空格等特殊字符,需要用引號把整個字符串括起來。
例如:$ PS1="OK> "
利用export命令將這些變量輸出,使它們成為公用量。如:
export HOME HZ LOGNAME TERM
可以利用env命令列出所有的環(huán)境變量,包括本進程及以前的“祖先進程”所輸出的變量
3.set命令
set命令的功能主要有三個:
⑴ 顯示迄今為止所定義的全部變量,包括局部量和公用量;
⑵ 用來設定位置參數(shù)的值;
⑶ 改變執(zhí)行shell腳本時的選項設定,可以使用戶改變shell的功能。
設置標志的一般形式是: set -標志
例如:set -x
關閉標志的一般形式是: set +標志
例如:set +x
作者: marquis 時間: 2013-5-5 01:18
4.7 參數(shù)置換變量
是另一種為變量賦值的方式,其一般形式是:
變量2=$ {變量1 op 字符串}
其中,op表示操作符,它可以是下列四個操作符之一:
:- : = : + : ?
變量2的值取決于變量1(參數(shù))是否為空串、利用哪個操作符以及字符串的取值。
在操作符的前后不留空格。
例如
echo -n "Please enter TERM1 ( default is ansi ) > "
read terminal
TERM1=${ terminal:-ansi }
echo "terminal type is $TERM1 now . "
echo "terminal=$terminal "
4.8 算 術 運 算
bash中執(zhí)行整數(shù)算術運算的命令是let,其語法格式為:
let arg …
其中arg是單獨的算術表達式。它使用C語言中表達式的語法、優(yōu)先級和結(jié)合性。除++、--和逗號(,)之外,所有整型運算符都得到支持,此外,還提供了方冪運算符“**”。
在算術表達式中直接利用名稱訪問命名的參數(shù),不要前面帶有“$”符號
let 命令的替代表示形式是:
((算術表達式))
例如:
let ″j=i*6+2″
等價于: ((j=i*6+2))
如果表達式的值是非0,那么返回的狀態(tài)值是0;否則,返回的狀態(tài)值是1。
當表達式中有shell的特殊字符時,必須用雙引號將其括起來。例如,let ″val=a|b″
只有使用 $((算術表達式))
形式才能返回表達式的值
4.9 控制流結(jié)構(gòu)
4.9.1 if語句
if語句用于條件控制結(jié)構(gòu)中,其一般格式為:
if 測試條件
then 命令1
else 命令2
fi
其中,if、then、else和fi是關鍵字。例如:
if test -f "$1"
then echo "$1 is an ordinary file . "
else echo "$1 is not an ordinary file . "
fi
if語句中else部分可以缺省。例如,
if test -f "$1"
then echo "$1 is an ordinary file . "
fi
if 語句的else部分還可以是else—if結(jié)構(gòu),則用關鍵字“elif”代替“else if”。例如,
if test - f "$1"
then pr $1
elif test - d "$1"
then ( cd $1 ; pr * )
else echo "$1 is neither a file nor a directory . "
fi
if的語句的更一般形式是:
if 命令表1
then 命令表2
else 命令表3
fi
4.9.2 條件測試
條件測試有三種常用形式:一種是用test 命令,如上所示。另一種是用一對方括號將測試條件括起來。這兩種形式是完全等價的。例如,測試位置參數(shù)$1是否是已存在的普通文件,可寫為:
test -f "$1"
也完全可寫成:[_ -f "$1“_]
第三種形式是: [[條件表達式]]
test命令可以和多種系統(tǒng)運算符一起使用。這些運算符可以分為四類:文件測試運算符、字符串測試運算符、數(shù)值測試運算符和邏輯運算符。
1.有關文件方面的測試
下載 (398.66 KB)
2013-5-5 01:15
2.有關字符串方面的測試
下載 (276.86 KB)
2013-5-5 01:16
3.有關數(shù)值方面的測試
下載 (185.69 KB)
2013-5-5 01:17
4.邏輯運算符 上述測試條件可以在if 語句或循環(huán)語句中單個使用,也可以通過邏輯運算符把它們組合起來使用?梢栽跍y試語句中使用的邏輯運算符有:
! 邏輯非( NOT ),它放在任意邏輯表達式之前,使原來為真的表達式變?yōu)榧,使原來為假的變(yōu)檎。例如?/font> [ ! -r $1 ] , ! test -r “$1”等。 - a 邏輯與( AND ),它放在兩個邏輯表達式中間,僅當兩個表達式都為真時,結(jié)果才為真。例如, [ - f "$myfile" - a - r “$myfile" ] - o 邏輯或( OR ),它放在兩個邏輯表達式中間,其中只要有一個表達式為真,結(jié)果就為真。例如, [ "$a" -ge 0 -o "$b" -le 100 ] (表達式) 圓括號,它可以把一個邏輯表達式括起來,使之成為一個整體,優(yōu)先得到運算。例如, [ \( "$a" -ge 0 \) -a \( "$b" -le 100 \) ]邏輯表達式中的條件測試運算符優(yōu)先級高于“!” 運算符,“!” 運算符的優(yōu)先級高于“ -a”運算符,“-a”運算符高于 “-o”,而且圓括號( )高于 “-a”
5.特殊條件測試(1) :表示不做任何事情,其退出值為0。(2)true 表示總為真,其退出值總是0。(3)false 表示總為假,其退出值是255。
圖片附件: 圖片11.png (2013-5-5 01:15, 398.66 KB) / 下載次數(shù) 9992
http://cd-genova.com/bbs/attachment.php?aid=2924&k=b314f4f6a281443ea8574d3ceb5eeee9&t=1744283754&sid=9vTNRC

圖片附件: 圖片12.png (2013-5-5 01:16, 276.86 KB) / 下載次數(shù) 9733
http://cd-genova.com/bbs/attachment.php?aid=2925&k=58112221f9aa19abb2fdc9b83455b0c5&t=1744283754&sid=9vTNRC

圖片附件: 圖片16.png (2013-5-5 01:17, 185.69 KB) / 下載次數(shù) 9654
http://cd-genova.com/bbs/attachment.php?aid=2926&k=4aadd07295bd50e36e7e2ebb64c2e53f&t=1744283754&sid=9vTNRC

作者: marquis 時間: 2013-5-5 01:24
4.9.3 case語句
case語句允許進行多重條件選擇。其一般語法形式是:
case 字符串 in
模式字符串1) 命令
…
命令;;
模式字符串2) 命令
…
命令;;
…
模式字符串n) 命令
…
命令;;
esac
在使用case語句時應注意:
⑴ 每個模式字符串后面可有一條或多條命令,其最后一條命令必須以兩個分號(即;;)結(jié)束。
⑵模式字符串中可以使用通配符
⑶ 如果一個模式字符串中包含多個模式,那么各模式之間應以豎線(|)隔開,表示各模式是“或”的關系,即只要給定字符串與其中一個模式相配,就會執(zhí)行其后的命令表
⑷ 各模式字符串應是唯一的,不應重復出現(xiàn)。并且要合理安排它們的出現(xiàn)順序。
⑸ case語句以關鍵字case開頭,以關鍵字esac(是case倒過來寫!)結(jié)束。
⑹ case的退出(返回)值是整個結(jié)構(gòu)中最后執(zhí)行的那個命令的退出值。若沒有執(zhí)行任何命令,則退出值為零
4.9.4 while語句
shell中有三種用于循環(huán)的語句,它們是:while語句、for語句和until語句。
while語句的一般形式是:
while 測試條件
do
命令表
done
測試條件部分除使用test命令或等價的方括號外,還可以是一組命令。根據(jù)其最后一個命令的退出值決定是否進入循環(huán)體執(zhí)行。
4.9.5 until語句
until語句的一般形式是:
until 測試條件
do
命令表
done
它與while語句很相似,只是測試條件不同:當測試條件為假時,才進入循環(huán)體,直至測試條件為真時終止循環(huán)。
4.9.6 for語句
其使用方式主要有兩種:一種是值表方式,另一種是算術表達式方式。
1.值表方式
其一般格式是:
for 變量 [ in 值表 ];do 命令表;done
根據(jù)循環(huán)變量的取值方式,其使用格式可分為三種:
格式一:
for 變量 in 值表
do
命令表
done
格式二:
for 變量 in 文件正則表達式
do
命令表
done
格式三:
for i in $* 或者 for i
do do
命令表 命令表
done done
2.算術表達式方式
其一般格式是:
for (( e1;e2;e3)) ; do 命令表;done
或者
for ((e1;e2;e3))
do
命令表
done
其中,e1, e2, e3是算術表達式。它的執(zhí)行過程與C語言中for語句相似,即:① 先按算術運算規(guī)則計算表達式e1;② 接著計算e2,如果e2值不為0,則執(zhí)行命令表中的命令,并且計算e3;然后重復②,直至e2為0,退出循環(huán)。
4.9.7 break命令和continue命令
1.break命令
break命令使程序從循環(huán)體中退出來。其語法格式是:
break [ n ]
2.continue命令
continue命令跳過循環(huán)體中在它之后的語句,回到本層循環(huán)的開頭,進行下一次循環(huán)。其語法格式是:
continue [ n ]
4.9.8 exit命令
exit命令的功能是立即退出正在執(zhí)行的shell腳本,并設定退出值。其語法格式是:
exit [ n ]
4.9.9 select語句
select 語句通常用于菜單的設計,它自動完成接收用戶輸入的整個過程,包括顯示一組菜單項以及讀入用戶的選擇。
select 語句的語法形式為:
select identifier[in word…]
do
命令表
done
如果in word…這一部分被省略,那么參數(shù)identifier就以位置參數(shù)($1, $2, …)作為給定的值。
4.10 函數(shù)
在shell腳本中可以定義并使用函數(shù)。其定義格式為:
[function]函數(shù)名( )
{
命令表
}
函數(shù)應先定義,后使用。調(diào)用函數(shù)時,直接利用函數(shù)名,如showfile,不必帶圓括號
shell腳本與函數(shù)間的參數(shù)傳遞可利用位置參數(shù)和變量直接傳遞
通常,函數(shù)中的最后一個命令執(zhí)行之后,就退出被調(diào)函數(shù)。也可利用return命令立即退出函數(shù),其語法格式是:
return [ n ]
4.11 作 業(yè) 控 制
執(zhí)行命令set -o monitor,則交互式shell就實施作業(yè)管理。作業(yè)管理的命令有jobs,kill,bg,fg和wait。
4.11.1 jobs命令
不帶參數(shù)時,可列出當前尚未完成的作業(yè)。例如:
$ jobs
[2] +Done
who|wc -cd
[1] -Stopped(SIGTTOU) man ls&
4.11.2 kill命令
使用kill命令可以向指定的進程發(fā)送TERM(終止)信號或者指定的信號。
其中一些信號可以使作業(yè)中止運行。
例如:kill -9 1893
信號可以由信號號碼(sig)或者信號名(signame)指定。利用kill -l命令可以列出全部信號名。
作者: marquis 時間: 2013-5-5 01:27
4.11.3 bg和fg命令
bg命令可以把前臺作業(yè)切換成后臺作業(yè)
其語法格式是:
bg [job …]
fg命令可以把后臺作業(yè)切換成前臺作業(yè)
其語法格式是:
fg [job…]
僅當作業(yè)控制被激活,這些命令才起作用
4.12 shell內(nèi)置命令
這些命令構(gòu)造在shell內(nèi)部,從而在shell進程內(nèi)執(zhí)行。已在前面介紹過的內(nèi)置命令:
:,. filename,break [ n ], continue [ n ], cd , echo, exit [ n ] , export, pwd, read, return [ n ] , set, shift [ n ] , test, bg, fg, kill等 。
1.eval命令
格式是: eval [ arg … ]
可以利用別的命令行作為自己的參數(shù)(arg),進行相應的變量或命令替換,并把替換結(jié)果結(jié)合成一個新的命令行,然后讀取并加以執(zhí)行。
#!/bin/bash
getc()
{
stty raw
tmp=`dd bs=1 count=1 2>/dev/null`
eval $1= ' $tmp'
stty cooked
}
press_any_key()
{
echo -n "Strike any key to continue…"
getc anychar
}
echo -n "Enter a character:"
getc char
echo
echo "You entered $char "
press_any_key char
echo
2.exec命令
格式是: exec [ arg … ]
在本shell中執(zhí)行由參數(shù)arg指定的命令,并不創(chuàng)建新進程
3.hash命令
格式是: hash [ -r ] [ name … ]
可以確定并記住由name指定的每個命令在搜索路徑中的位置。
4.readonly命令
格式是: readonly [ name … ]
標記給定的name(變量名)是只讀的,以后不能通過賦值語句改變其值
5.trap命令
用來設定接收到某個信號所完成的動作,忽略某個信號的影響或者恢復該信號產(chǎn)生時系統(tǒng)預設的動作。
其格式是: trap [ arg ] [ n ] …
①為某些信號另外指定處理方式。例如:
trap 'rm - f $temp ; exit ' 0 1 2 3 15
②如果arg是空串,如 :
trap "" 2
那么,信號2就被shell和它引用的命令忽略。
③如果缺省arg,則把所有陷入信號n的動作恢復成原來系統(tǒng)設置的動作。如:
trap 1 2
④如果trap命令后面沒有任何參數(shù),則顯示與每個信號相關的命令表。
6.type命令
格式是: type [ name … ]
功能是,對于每一個name,如果作為命令名,它是如何被解釋的,如內(nèi)置命令、一般命令搜索路徑等。
7.unset命令
格式是:unset [ name … ]
刪除由name指定的相應變量或函數(shù)。
應注意,變量PATH,PS1,PS2,MAILCHECK和IFS不能被刪除,即不能受unset的作用。
8.umask命令
格式是umask [-S ] [ mask ]
將用戶文件創(chuàng)建掩碼設置為mask的值。
9.wait命令
格式是:wait [ n ]
等待由n(進程 ID)指定的進程終止,并報告終止狀態(tài)。
4.13 shell腳本調(diào)試
通常采用自底向上的方法,即:先搞清楚要腳本做什么,然后將過程的連續(xù)階段分解為獨立的步驟,最后利用shell提示符,交互式地檢查和調(diào)試每個獨立的步驟。
編寫的腳本無法執(zhí)行的原因除腳本文件缺少“執(zhí)行”權限外,有兩種可能:執(zhí)行腳本的環(huán)境設置不對和腳本本身有錯誤。
4.13.1 解決環(huán)境設置問題
① 不能直接在其他shell下運行bash腳本,解決的辦法是在腳本的第一行寫上:#!/bin/bash
② 在PATH環(huán)境變量中沒有包括“.”(當前工作目錄)。
解決辦法是設置PATH:PATH=$PATH:.
③ 腳本文件與已存在命令的名字相同。
4.13.2 解決腳本錯誤
基本的錯誤類型有兩種:語法錯誤和邏輯錯誤。
語法錯誤是編寫程序時違反了所用編程語言的規(guī)則而造成的。
邏輯錯誤通常是由于程序的邏輯關系存在問題。對此類問題需要進行程序調(diào)試。
一個很有用的技巧是使用set命令打開-x選項,或者在啟動shell時使用-x選項將shell設置成跟蹤模式。
另一個有用的技巧是在程序中經(jīng)常使用echo或print命令
作者: admin 時間: 2013-5-5 20:36
很好
歡迎光臨 WDlinux官方論壇 (http://cd-genova.com/bbs/) |
Powered by Discuz! 7.2 |