Shell语句
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
●Shell語(yǔ)句
■Shell注釋
以“#”開(kāi)頭的行就是注釋,會(huì)被解釋器忽略。
sh里沒(méi)有多行注釋,只能每一行加一個(gè)#號(hào)。只能一行行注。
?
如果在開(kāi)發(fā)過(guò)程中,遇到大段的代碼需要臨時(shí)注釋起來(lái),過(guò)一會(huì)兒又取消注釋,怎么辦呢?每一行加個(gè)#符號(hào)太費(fèi)力了,可以把這一段要注釋的代碼用一對(duì)花括號(hào)括起來(lái),定義成一個(gè)函數(shù),沒(méi)有地方調(diào)用這個(gè)函數(shù),這塊代碼就不會(huì)執(zhí)行,達(dá)到了和注釋一樣的效果。
?
■Shell echo命令
echo是Shell的一個(gè)內(nèi)部指令,用于在屏幕上打印出指定的字符串。命令格式:
echo arg
您可以使用echo實(shí)現(xiàn)更復(fù)雜的輸出格式控制。
顯示轉(zhuǎn)義字符
?
echo "\"It is a test\""
結(jié)果將是:
"It is a test"
?
雙引號(hào)也可以省略。
顯示變量
?
name="OK"
echo "$name It is a test"
結(jié)果將是:
OK It is a test
?
同樣雙引號(hào)也可以省略。
?
如果變量與其它字符相連的話,需要使用大括號(hào)({ }):
mouth=8
echo "${mouth}-1-2009"
結(jié)果將是:
8-1-2009
顯示換行
?
echo "OK!\n"
echo "It is a test"
輸出:
OK!
It is a test
顯示不換行
?
echo "OK!\c"
echo "It is a test"
輸出:
OK!It si a test
顯示結(jié)果重定向至文件
?
echo "It is a test" > myfile
原樣輸出字符串
?
若需要原樣輸出字符串(不進(jìn)行轉(zhuǎn)義),請(qǐng)使用單引號(hào)。例如:
echo '$name\"'
顯示命令執(zhí)行結(jié)果
?
echo `date`
結(jié)果將顯示當(dāng)前日期
?
從上面可看出,雙引號(hào)可有可無(wú),單引號(hào)主要用在原樣輸出中。
?
■shell printf命令
格式化輸出語(yǔ)句printf 命令用于格式化輸出, 是echo命令的增強(qiáng)版。
??? printf 不像 echo 那樣會(huì)自動(dòng)換行,必須顯式添加換行符(\n)。
printf 命令的語(yǔ)法:
printf? format-string? [arguments...]
format-string 為格式控制字符串,arguments 為參數(shù)列表。
這里僅說(shuō)明與C語(yǔ)言printf()函數(shù)的不同:
printf 命令不用加括號(hào)
format-string 可以沒(méi)有引號(hào),但最好加上,單引號(hào)雙引號(hào)均可。
參數(shù)多于格式控制符(%)時(shí),format-string 可以重用,可以將所有參數(shù)都轉(zhuǎn)換。
arguments 使用空格分隔,不用逗號(hào)。
注意,根據(jù)POSIX標(biāo)準(zhǔn),浮點(diǎn)格式%e、%E、%f、%g與%G是“不需要被支持”。這是因?yàn)閍wk支持浮點(diǎn)預(yù)算,且有它自己的printf語(yǔ)句。這樣Shell程序中需要將浮點(diǎn)數(shù)值進(jìn)行格式化的打印時(shí),可使用小型的awk程序?qū)崿F(xiàn)。然而,內(nèi)建于bash、ksh93和zsh中的printf命令都支持浮點(diǎn)格式。
?
■Shell if else語(yǔ)句
if 語(yǔ)句通過(guò)關(guān)系運(yùn)算符判斷表達(dá)式的真假來(lái)決定執(zhí)行哪個(gè)分支。Shell 有三種 if ... else 語(yǔ)句:
if ... fi 語(yǔ)句;
if ... else ... fi 語(yǔ)句;
if ... elif ... else ... fi 語(yǔ)句。
?
1) if ... else 語(yǔ)句
if ... else 語(yǔ)句的語(yǔ)法:
if command
then
?? Statement(s) to be executed if expression is true
fi
如果command返回 0(正常值),then 后邊的語(yǔ)句將會(huì)被執(zhí)行;如果返回 不是0(錯(cuò)誤值),不會(huì)執(zhí)行任何語(yǔ)句。
?
最后必須以 fi 來(lái)結(jié)尾閉合 if,fi 就是 if 倒過(guò)來(lái)拼寫(xiě),后面也會(huì)遇見(jiàn)。
?
注意:expression 和方括號(hào)([ ])之間必須有空格,否則會(huì)有語(yǔ)法錯(cuò)誤。
?
2) if ... else ... fi 語(yǔ)句
if ... else ... fi 語(yǔ)句的語(yǔ)法:
if command
then
?? Statement(s) to be executed if expression is true
else
?? Statement(s) to be executed if expression is not true
fi
如果command返回 0,那么 then 后邊的語(yǔ)句將會(huì)被執(zhí)行;否則,執(zhí)行 else 后邊的語(yǔ)句。
?
3) if ... elif ... fi 語(yǔ)句
if ... elif ... fi 語(yǔ)句可以對(duì)多個(gè)條件進(jìn)行判斷,語(yǔ)法為:
if command 1
then
?? Statement(s) to be executed if expression 1 is true
elif command 2
then
?? Statement(s) to be executed if expression 2 is true
else
?? Statement(s) to be executed if no expression is true
fi
哪一個(gè)command的值為 0,就執(zhí)行哪個(gè)command后面的語(yǔ)句;如果都為 false,那么不執(zhí)行任何語(yǔ)句。
if ... else 語(yǔ)句也可以寫(xiě)成一行,以命令的方式來(lái)運(yùn)行,像這樣:
if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;
?
if ... else 語(yǔ)句也經(jīng)常與 test 命令結(jié)合使用,如下所示:
num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
??? echo 'The two numbers are equal!'
else
??? echo 'The two numbers are not equal!'
fi
輸出:
The two numbers are equal!
test 命令用于檢查某個(gè)條件是否成立,與方括號(hào)([ ])類似。
因?yàn)榻?jīng)常使用test,可以使用方括號(hào)、中括號(hào)來(lái)達(dá)到同樣的效果,[也是test,但必須有空格。
?
■Shell case esac語(yǔ)句
case 值 in
??? 模式1)
??????? command1
??????? command2
??????? command3
??????? ;;
注意:后面有兩個(gè)分號(hào)
case ... esac 與其他語(yǔ)言中的 switch ... case 語(yǔ)句類似,是一種多分枝選擇結(jié)構(gòu)。
?
case 語(yǔ)句匹配一個(gè)值或一個(gè)模式,如果匹配成功,執(zhí)行相匹配的命令。case語(yǔ)句格式如下:
case 值 in
模式1)
??? command1
??? command2
??? command3
??? ;;
模式2)
??? command1
??? command2
??? command3
??? ;;
*)
??? command1
??? command2
??? command3
??? ;;
esac
case工作方式如上所示。取值后面必須為關(guān)鍵字 in,每一模式必須以右括號(hào)結(jié)束。取值可以為變量或常數(shù)。匹配發(fā)現(xiàn)取值符合某一模式后,其間所有命令開(kāi)始執(zhí)行直至 ;;。;; 與其他語(yǔ)言中的 break 類似,意思是跳到整個(gè) case 語(yǔ)句的最后。
?
取值將檢測(cè)匹配的每一個(gè)模式。一旦模式匹配,則執(zhí)行完匹配模式相應(yīng)命令后不再繼續(xù)其他模式。如果無(wú)一匹配模式,使用星號(hào) * 捕獲該值,再執(zhí)行后面的命令。
?
下面的腳本提示輸入1到4,與每一種模式進(jìn)行匹配:
echo 'Input a number between 1 to 4'
echo 'Your number is:\c'
read aNum
case $aNum in
??? 1)? echo 'You select 1'
??? ;;
??? 2)? echo 'You select 2'
??? ;;
??? 3)? echo 'You select 3'
??? ;;
??? 4)? echo 'You select 4'
??? ;;
??? *)? echo 'You do not select a number between 1 to 4'
??? ;;
esac
輸入不同的內(nèi)容,會(huì)有不同的結(jié)果,例如:
Input a number between 1 to 4
Your number is:3
You select 3
?
再舉一個(gè)例子:
#!/bin/bash
option="${1}"
case ${option} in
?? -f) FILE="${2}"
????? echo "File name is $FILE"
????? ;;
?? -d) DIR="${2}"
????? echo "Dir name is $DIR"
????? ;;
?? *)
????? echo "`basename ${0}`:usage: [-f file] | [-d directory]"
????? exit 1 # Command to come out of the program with status 1
????? ;;
esac
運(yùn)行結(jié)果:
$./test.sh
test.sh: usage: [ -f filename ] | [ -d directory ]
$ ./test.sh -f index.htm
$ vi test.sh
$ ./test.sh -f index.htm
File name is index.htm
$ ./test.sh -d unix
Dir name is unix
$
?
■Shell select語(yǔ)句
select格式如下:
select name?? [in?? list ]
do
??? statements that can use? $name...
done
#!/bin/bash
#save? $PS3
oPS3=$PS3
PS3="請(qǐng)選擇喜歡的水果q退出:"
?
select fruit in pear apple banana? others? quit
do
??????? if [ ! -z "$fruit" ] ; then
??????????????? [ "$fruit" == "quit" ] && exit 0 || echo "you choosed $REPLY and you like $fruit"
??????? else???
??????????????????????? echo "wrong argv $REPLY"
??????? fi
done
#restore $PS3
PS3=$oPS3
# ./select.sh
1) pear
2) apple
3) banana
4) others
5) quit
請(qǐng)選擇喜歡的水果q退出:1
you choosed 1 and you like pear
請(qǐng)選擇喜歡的水果q退出:6
wrong argv 6
請(qǐng)選擇喜歡的水果q退出:5
$PS3變量相當(dāng)于shell的默認(rèn)提示符,默認(rèn)為空,可以配合select使用。
?
select也是循環(huán)的一種,它比較適合用在用戶選擇的情況下。
比如,我們有一個(gè)這樣的需求,運(yùn)行腳本后,讓用戶去選擇數(shù)字,選擇1,會(huì)運(yùn)行w命令,選擇2運(yùn)行top命令,選擇3運(yùn)行free命令,選擇4退出。
#!/bin/bash
echo "Please chose a number, 1: run w, 2: run top, 3: run free, 4: quit"
echo
select command in w top free quit
do
??? case $command in
??? w)
??????? w
??????? ;;
??? top)
??????? top
??????? ;;
??? free)
??????? free
??????? ;;
??? quit)
??????? exit
??????? ;;
??? *)
??????? echo "Please input a number:(1-4)."
??????? ;;
??? esac
done
?
■Shell for循環(huán)
與其他編程語(yǔ)言類似,Shell支持for循環(huán)。
?
for循環(huán)一般格式為:
for 變量 in 列表
do
??? command1
??? command2
??? ...
??? commandN
done
列表是一組值(數(shù)字、字符串等)組成的序列,每個(gè)值通過(guò)空格分隔。每循環(huán)一次,就將列表中的下一個(gè)值賦給變量。
?
in 列表是可選的,如果不用它,for 循環(huán)使用命令行的位置參數(shù)。
?
例如,順序輸出當(dāng)前列表中的數(shù)字:
for loop in 1 2 3 4 5
do
??? echo "The value is: $loop"
done
運(yùn)行結(jié)果:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
?
順序輸出字符串中的字符:
for str in 'This is a string'
do
??? echo $str
done
運(yùn)行結(jié)果:
This is a string
?
顯示主目錄下以 .bash 開(kāi)頭的文件:
#!/bin/bash
for FILE in $HOME/.bash*
do
?? echo $FILE
done
運(yùn)行結(jié)果:
/root/.bash_history
/root/.bash_logout
/root/.bash_profile
/root/.bashrc
?
$ cat test14.sh
#!/bin/bash
for((i=1;i<=10;i++))
do
??? echo ${i}
done
?
$ ./test14.sh
1
2
3
4
5
6
7
8
9
10
?
■Shell while循環(huán)
while循環(huán)用于不斷執(zhí)行一系列命令,也用于從輸入文件中讀取數(shù)據(jù);命令通常為測(cè)試條件。其格式為:
while command
do
?? Statement(s) to be executed if command is true
done
命令執(zhí)行完畢,控制返回循環(huán)頂部,從頭開(kāi)始直至測(cè)試條件為假。
?
以下是一個(gè)基本的while循環(huán),測(cè)試條件是:如果COUNTER小于5,那么返回 true。COUNTER從0開(kāi)始,每次循環(huán)處理時(shí),COUNTER加1。運(yùn)行上述腳本,返回?cái)?shù)字1到5,然后終止。
COUNTER=0
while [ $COUNTER -lt 5 ]
do
??? COUNTER='expr $COUNTER+1'
??? echo $COUNTER
done
運(yùn)行腳本,輸出:
1
2
3
4
5
?
while循環(huán)可用于讀取鍵盤(pán)信息。下面的例子中,輸入信息被設(shè)置為變量FILM,按<Ctrl-D>結(jié)束循環(huán)。
echo 'type <CTRL-D> to terminate'
echo -n 'enter your most liked film: '
while read FILM
do
??? echo "Yeah! great film the $FILM"
done
運(yùn)行腳本,輸出類似下面:
type <CTRL-D> to terminate
enter your most liked film: Sound of Music
Yeah! great film the Sound of Music
?
■Shell until循環(huán)
until 循環(huán)執(zhí)行一系列命令直至條件為 true 時(shí)停止。until 循環(huán)與 while 循環(huán)在處理方式上剛好相反。一般while循環(huán)優(yōu)于until循環(huán),但在某些時(shí)候,也只是極少數(shù)情況下,until 循環(huán)更加有用。
?
until 循環(huán)格式為:
until command
do
?? Statement(s) to be executed until command is true
done
command 一般為條件表達(dá)式,如果返回值為 false,則繼續(xù)執(zhí)行循環(huán)體內(nèi)的語(yǔ)句,否則跳出循環(huán)。
?
例如,使用 until 命令輸出 0 ~ 9 的數(shù)字:
#!/bin/bash
a=0
until [ ! $a -lt 10 ]
do
?? echo $a
?? a=`expr $a + 1`
done
運(yùn)行結(jié)果:
0
1
2
3
4
5
6
7
8
9
?
?
■Shell break和continue命令
在循環(huán)過(guò)程中,有時(shí)候需要在未達(dá)到循環(huán)結(jié)束條件時(shí)強(qiáng)制跳出循環(huán),像大多數(shù)編程語(yǔ)言一樣,Shell也使用 break 和 continue 來(lái)跳出循環(huán)。
??? break命令
??? break命令允許跳出所有循環(huán)(終止執(zhí)行后面的所有循環(huán))。
在嵌套循環(huán)中,break 命令后面還可以跟一個(gè)整數(shù),表示跳出第幾層循環(huán)。
?
??? continue命令
??? continue命令與break命令類似,只有一點(diǎn)差別,它不會(huì)跳出所有循環(huán),僅僅跳出當(dāng)前循環(huán)
同樣,continue 后面也可以跟一個(gè)數(shù)字,表示跳出第幾層循環(huán)。
?
exit命令(額外)
exit命令用于退出當(dāng)前shell,在shell腳本中可以終止當(dāng)前腳本執(zhí)行。
?
常用參數(shù)
格式:exit n
退出。設(shè)置退出碼為n。(Cause the shell to exit with a status of n.)
?
格式:exit
退出。退出碼不變,即為最后一個(gè)命令的退出碼。(If n is omitted, the exit status is that of the? last? command executed. )
?
格式:$?
上一個(gè)命令的退出碼。
?
格式:trap "commands" EXIT
退出時(shí)執(zhí)行commands指定的命令。( A trap on EXIT is executed before the shell terminates.)
?
退出碼(exit status,或exit code)的約定:
0表示成功(Zero - Success)
非0表示失敗(Non-Zero? - Failure)
2表示用法不當(dāng)(Incorrect Usage)
127表示命令沒(méi)有找到(Command Not Found)
126表示不是可執(zhí)行的(Not an executable)
>=128 信號(hào)產(chǎn)生
?
man 3 exit 寫(xiě)道
The C standard specifies two constants, EXIT_SUCCESS and EXIT_FAILURE, that may be passed to exit() to indicate
successful or unsuccessful termination, respectively.
?
以下摘自/usr/include/stdlib.h
#define EXIT_FAILURE??? 1?????? /* Failing exit status.? */?
#define EXIT_SUCCESS??? 0?????? /* Successful exit status.? */?
?
BSD試圖對(duì)退出碼標(biāo)準(zhǔn)化。
man 3 exit 寫(xiě)道
BSD has attempted to standardize exit codes; see the file <sysexits.h>.
?
?
以下摘自/usr/include/sysexits.h
#define EX_OK?????????? 0?????? /* successful termination */?
?
#define EX__BASE??????? 64????? /* base value for error messages */?
?
#define EX_USAGE??????? 64????? /* command line usage error */?
#define EX_DATAERR????? 65????? /* data format error */?
#define EX_NOINPUT????? 66????? /* cannot open input */?
#define EX_NOUSER?????? 67????? /* addressee unknown */?
#define EX_NOHOST?????? 68????? /* host name unknown */?
#define EX_UNAVAILABLE? 69????? /* service unavailable */?
#define EX_SOFTWARE???? 70????? /* internal software error */?
#define EX_OSERR??????? 71????? /* system error (e.g., can't fork) */?
#define EX_OSFILE?????? 72????? /* critical OS file missing */?
#define EX_CANTCREAT??? 73????? /* can't create (user) output file */?
#define EX_IOERR??????? 74????? /* input/output error */?
#define EX_TEMPFAIL???? 75????? /* temp failure; user is invited to retry */?
#define EX_PROTOCOL???? 76????? /* remote error in protocol */?
#define EX_NOPERM?????? 77????? /* permission denied */?
#define EX_CONFIG?????? 78????? /* configuration error */?
?
#define EX__MAX 78????? /* maximum listed value */
?
shell退出狀態(tài)
exit 使shell(腳本)以指定狀態(tài)值退出, 不帶參數(shù)執(zhí)行exit時(shí),shell或腳本以最后執(zhí)行命令的狀態(tài)值退出。 shell退出前, trap會(huì)捕獵EXIT信號(hào)。0表示執(zhí)行成功,非0值表執(zhí)行失敗。它經(jīng)常用于判斷語(yǔ)句和循環(huán)語(yǔ)句來(lái)控制程序和表達(dá)式的流程。
exit 使得編寫(xiě)腳本時(shí)可以自行設(shè)置退出時(shí)的狀態(tài)值,使用$?引用,特定的退出狀態(tài)值一般也會(huì)定義特定的退出含義。也可以用test來(lái)檢查表達(dá)式的退出狀態(tài)。
bash 所有builtin 命令都會(huì)在成功時(shí)返回狀態(tài)0,失敗時(shí)返回非0,所以它們可以用于條件命令和命令list中
?
exit status退出狀態(tài)
執(zhí)行某一函數(shù),程序或命令后退出時(shí),向父命令返回一個(gè)整數(shù),這個(gè)稱為退出狀態(tài)。不帶參數(shù)的exit,則退出狀態(tài)為最后被執(zhí)行命令的退出狀態(tài)。父進(jìn)程可以中可以用$?引用其值
判斷語(yǔ)句和循環(huán)語(yǔ)句也會(huì)用到exit status內(nèi)置命令來(lái)控制程序流程,用來(lái)返回給父進(jìn)程一個(gè)status值且腳本退出,且返回值保存在$?中, status 用0~255 之間的數(shù)字表示,這樣實(shí)現(xiàn)腳本主動(dòng)控制返回值。
?
POSIX規(guī)定的幾種退出狀態(tài)
0 運(yùn)行成功
1~125 各種運(yùn)行失敗
126 找到命令,但無(wú)法執(zhí)行
127 未找到運(yùn)行的命令
>128 命令被系統(tǒng)強(qiáng)行結(jié)束
?
sysopsis
exit [status value]
status value? 0~255 值保存在?變量中
?
eg
exit 退出shell,不改變$?的值
exit 1 退出shell, 且返回1
?
比較return
exit是一個(gè)系統(tǒng)調(diào)用,用于在程序運(yùn)行的過(guò)程中隨時(shí)結(jié)束進(jìn)程,它會(huì)刪除進(jìn)程占用的內(nèi)存空間,并將status是返回給父進(jìn)程,這個(gè)status通常用于標(biāo)識(shí)程序的一些運(yùn)行信息。
?
return是語(yǔ)言級(jí)別的一個(gè)關(guān)鍵字,它表示調(diào)用堆棧的返回,用于帶一個(gè)status從函數(shù)退出。return不帶參數(shù)時(shí),則會(huì)返回函數(shù)體中最后一個(gè)命令的返回值。
return 也可以用于. (source) 方式(子shell)執(zhí)行腳本時(shí)的返回,也可以返回指定的status 或者腳本中最后一個(gè)命令的exit status.
return 不用于函數(shù)體,也沒(méi)有以.(source)方式執(zhí)行腳本時(shí),則會(huì)報(bào)錯(cuò)。
return會(huì)觸發(fā)trap
?
所以正確的用法是將return 用于函數(shù)的返回,exit用于進(jìn)程的退出。比如如果主函數(shù)調(diào)用子函數(shù),在子函數(shù)里使用return會(huì)回到主函數(shù)中,但在子函數(shù)中誤用exit則會(huì)直接退出進(jìn)程。
轉(zhuǎn)載于:https://my.oschina.net/dubenju/blog/871030
總結(jié)