bash的工作特性之命令執(zhí)行狀態(tài)返回值
一熄守、shell是什么睦疫?
Shell本身是一個(gè)用C語(yǔ)言編寫的程序判耕,它是用戶使用Unix/Linux的橋柑蛇,用戶的大部分工作都是通過(guò)Shell完成的。Shell既是一種命令語(yǔ)言兆龙,又是一種程序設(shè)計(jì)語(yǔ)言杖爽。作為命令語(yǔ)言,它交互式地解釋和執(zhí)行用戶輸入的命令紫皇;作為程序設(shè)計(jì)語(yǔ)言慰安,它定義了各種變量和參數(shù),并提供了許多在高級(jí)語(yǔ)言中才具有的控制結(jié)構(gòu)聪铺,包括循環(huán)和分支化焕。
shell是一個(gè)應(yīng)用程序,是用戶管理應(yīng)用程序的一個(gè)接口铃剔。
二撒桨、廣義上shell的分類
GUI:圖形用戶界面
KDE,GNOME键兜,XFCE
CLI:命令行接口
bash, zsh, fishsh, csh, tcsh, ksh
在大多發(fā)行版中常用的為bash
三凤类、bash的特性
bash是弱類型的編程語(yǔ)言,不嚴(yán)格區(qū)分?jǐn)?shù)據(jù)類型普气,意味把所有數(shù)據(jù)統(tǒng)統(tǒng)當(dāng)作字符串處理谜疤;
字符串類型的數(shù)據(jù)可不加引號(hào);
引號(hào)有三種類型:', ", `
', ":字符引用
': 強(qiáng)引用现诀,其內(nèi)部的變量不會(huì)被替換夷磕;
":弱引用,其內(nèi)部的變量會(huì)被替換仔沿;
`:命令引用
變量引用:${NAME}
a坐桩、bash特性之一:命令別名
獲取當(dāng)前用戶可用的別名的定義:
1 # alias
定義別名:
1 # alias NAME='COMMAND'
生命周期:當(dāng)前shell進(jìn)程;
1 # unalias NAME
撤消別名:
b于未、bash的特性之二:命令歷史
shell進(jìn)程會(huì)保存其會(huì)話中用戶曾經(jīng)執(zhí)行過(guò)的命令;命令通過(guò)其“歷史文件”來(lái)持久保存此前執(zhí)行過(guò)的命令;每個(gè)用戶都有其自己專用的歷史文件烘浦;
HISTSIZE:shell進(jìn)程的緩沖區(qū)保留的歷史命令的條數(shù)抖坪;
HISTFILESIZE:命令歷史文件可保存的歷史命令的條數(shù);
默認(rèn)均為1000;
1 # echo $HISTSIZE
2 1000
3 # echo $HISTFILESIZE
4 1000
HISTFILE:當(dāng)前用戶的命令歷史文件;
~/.bash_history
查看命令歷史列表:
1 # history
命令用法:
history -c:清空命令歷史;
history -d OFFSET:刪除指定的條目逃糟;
1 # history -d 156
-a 將當(dāng)前緩沖的歷史行追加到歷史文件中
-n 從歷史文件中讀取所有未被讀取的行
-r 讀取歷史文件并將內(nèi)容追加到歷史列表中
調(diào)用命令歷史列表中的命令以重執(zhí)行之目的:
!#:再一次執(zhí)行歷史列表中的第#條命令泊窘;
1 # history
2 ....
3 72 cat test
4 73 history
5 # !72
6 cat test
7 Hello World
!!:再一次執(zhí)行上一條命令;
1 # cat test
2 Hello World
3 # !!
4 cat test
5 Hello World
!STRING:再一次執(zhí)行命令歷史列表中最近一個(gè)以指定的STRING開頭的命令勇凭;
1 # !cat
2 cat test
3 Hello World
調(diào)用上一條命令的最后一個(gè)參數(shù):
快捷鍵:ESC, .
Alt+.
!$:給出的字符組合
顯示最近的n條件命令歷史:
history #
控制命令歷史的記錄方式:
通過(guò)HISTCONTROL環(huán)境變量進(jìn)行,其取值:
ignoredups:忽略重復(fù)的命令;重復(fù)是指連續(xù)且相同的令埋合;
ignorespace:以空白字符開頭的命令不記入歷史;
ignoreboth:上述兩者同時(shí)生效萄传;
修改變量值的方式:
NAME='VALUE'
1 # echo $HISTCONTROL
2 ignoredups
3 # HISTCONTROL="ignoreboth"
4 # echo $HISTCONTROL
5 ignoreboth
c甚颂、bash特性之三:快捷鍵
Ctrl+a:跳至命令行首;
Ctrl+e:跳至命令行尾秀菱;
Ctrl+k:刪除光標(biāo)所在處至尾部的內(nèi)容振诬;
Ctrl+u:刪除行首至光標(biāo)所在處的內(nèi)容;
d衍菱、bash的特性之四:命令補(bǔ)全和路徑補(bǔ)全
命令補(bǔ)全:
shell程序在接收到用戶執(zhí)行命令的請(qǐng)求且分析完成之后赶么,最左側(cè)字符串將被當(dāng)作命令去查找;
查找機(jī)制:
(1) 查找內(nèi)部命令脊串;
(2) 查找外部命令:
1辫呻、去$PATH變量所指定的各路徑下,自左而右逐個(gè)搜索各目錄下的文件名洪规;
2印屁、給定的打頭的字符串如果能惟一標(biāo)識(shí)某命令程序文件的文件名,則直接補(bǔ)全斩例;
3雄人、不能惟一標(biāo)識(shí),再擊tab可給列表念赶;
4础钠、錯(cuò)誤:沒有任何命令可被此打頭字符串標(biāo)識(shí);
路徑補(bǔ)全:
在給定的起始路徑的上級(jí)目錄下叉谜,以對(duì)應(yīng)路徑下的打頭字符串來(lái)逐一匹配上級(jí)目標(biāo)下的每個(gè)文件:
惟一標(biāo)識(shí):tab補(bǔ)全旗吁;
不能惟一標(biāo)識(shí):tab, tab給出列表;
錯(cuò)誤路徑:沒有響應(yīng)停局;
e很钓、bash的特性之五:命令行展開:
把命令行的給定的特殊符號(hào)自動(dòng)替換為相應(yīng)字符串的機(jī)制香府;
~: 自動(dòng)替換為用戶家目錄;
~USERNAME:自動(dòng)替換為指定用戶的家目錄码倦;
{}:可承載一個(gè)以逗號(hào)分隔的路徑列表企孩,能夠?qū)⑵湔归_為多個(gè)獨(dú)立路徑;
例如:
/tmp/{a,b,c} /tmp/a /tmp/b /tmp/c
/tmp/{a,b}/z /tmp/a/z /tmp/b/z
1 # cd ~
2 # pwd
3 /root
4 # cd ~testuser
5 testuser]# pwd
6 /home/testuser
f袁稽、bash特性之六:命令的執(zhí)行狀態(tài)結(jié)果:
命令的正常輸出結(jié)果:命令的返回值勿璃;
通過(guò)引用來(lái)保存下來(lái)或直接調(diào)用——“命令引用”
'COMMAND'
$(COMMAND)
1 # ls -ld 'pwd'
命令的執(zhí)行狀態(tài)結(jié)果:
成功:0
失敗:1-255
1 # echo "Helllo World"
2 Helllo World
3 # echo $?
4 0
5 # echoa "Hello World"
6 -bash: echoa: command not found
7 # echo $?
8 127
bash用一個(gè)特殊變量來(lái)保存最一次執(zhí)行的命令的狀態(tài)結(jié)果:
$?
bash中的引用:
'':強(qiáng)引用
"":弱引用
“:命令引用
1 # echo '$PATH'
2 $PATH
3 # echo "$PATH"
4 /usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin5 :/usr/bin:/root/bin
6 # echo 'pwd'
7 /home/testuser
g推汽、bash的特性之七:glob
glob:文件名通配补疑;快速引用多個(gè)文件;文件名整體匹配度檢測(cè)歹撒;
元字符:基于元字符可編寫匹配模式(pattern)莲组;
*:匹配任意長(zhǎng)度的任意字符;
p栈妆,pa胁编,,p鳞尔,pa
p*:pa, p
?:匹配任意單個(gè)字符嬉橙;
p?, p?a, p??
p??: pa, pad,
[ ]:匹配指定集合內(nèi)的任意單個(gè)字符;
[a-z], [A-Z]:不區(qū)分字符大小寫寥假;
[0-9]
[a-z0-9]
[[:upper:]]:所有大寫字母市框;
[[:lower:]]:所有小寫字母;
[[:digit:]]:所有的數(shù)字糕韧;
[[:alpha:]]:所有字母枫振;
[[:alnum:]]:所有字母和數(shù)字;
[[:space:]]:空白字符萤彩;
[[:punct:]]:標(biāo)點(diǎn)符號(hào)粪滤;
[^ ]:匹配指定集合外的任意單個(gè)字符;
[^[:alpha:]]
測(cè)試:
1雀扶、顯示/etc目錄下杖小,以非字母開頭,后面跟了一個(gè)字母及其它任意長(zhǎng)度任意字符的文件或目錄愚墓;
ls -d /etc/[^[:alpha:]][a-z]*
2予权、復(fù)制/etc目錄下,所以n開頭浪册,以非數(shù)字結(jié)尾的文件或目錄至/tmp/etc目錄下扫腺;
mkdir /tmp/etc
cp -r /etc/n*[^0-9] /tmp/etc/
3、顯示/usr/share/man目錄下村象,所有以man開頭笆环,后跟一個(gè)數(shù)字結(jié)尾的文件或目錄攒至;
ls -d /ur/share/man/man[0-9]
4、復(fù)制/etc目錄下躁劣,所以p,m,r開頭的嗓袱,且以.conf結(jié)尾的文件或目錄至/tmp/conf.d目錄下;
mkdir /tmp/conf.d/
cp -r /etc/[pmr]*.conf /tmp/conf.d/
h习绢、bash特性之八:變量
程序:指令+數(shù)據(jù)
數(shù)據(jù):文件、變量蝙昙;
變量:內(nèi)存空間闪萄,有名稱,名稱即為變量名奇颠,對(duì)應(yīng)的內(nèi)存空間中的數(shù)據(jù)即為變量的值败去;
變量賦值:NAME=VALUE
=:賦值符號(hào);
把VALUE存儲(chǔ)到NAME指向的內(nèi)存空間中烈拒;
編程語(yǔ)言:
強(qiáng)類型:嚴(yán)格區(qū)分變量中的數(shù)據(jù)類型圆裕;
弱類型:不區(qū)分變量中存儲(chǔ)的數(shù)據(jù)類型,統(tǒng)一為字符型荆几;
bash:統(tǒng)統(tǒng)默認(rèn)為字符型數(shù)據(jù)吓妆;變量無(wú)需事先聲明;
變量為什么有類型吨铸?
存儲(chǔ)空間行拢、存儲(chǔ)格式、參與的運(yùn)算诞吱、……
類型不同決定對(duì)數(shù)據(jù)的處理方式不同
變量命名:只能使用字母舟奠、數(shù)字和下劃線;而且不能以數(shù)字開頭房维;
變量名:見名知義沼瘫;不能使用程序保留字,例如if咙俩、case耿戚、then、fi暴浦、esac溅话、for、while歌焦、until飞几、break、continue等等独撇;
變量引用:${NAME}, $NAME
變量替換:把變量引用符號(hào)出現(xiàn)的位置替換為其指向的內(nèi)存空間中的數(shù)據(jù)屑墨;
bash變量種類:
本地變量:作用域?yàn)楫?dāng)前shell進(jìn)程躁锁;不包括其子進(jìn)程;
環(huán)境變量:使用域?yàn)楫?dāng)前shell進(jìn)程及其子進(jìn)程卵史;
局部變量
作用域:生效范圍战转,也即可引用到的范圍;
位置參數(shù)變量:
特殊變量
本地變量:
變量賦值:NAME=VALUE
變量引用:$NAME, ${NAME}
""
查看變量:set
撤銷變量:unset NAME
注意:此處非為變量引用以躯,因此不能使用$槐秧;
所有的本地變量在shell進(jìn)程終止時(shí),會(huì)被自動(dòng)撤銷忧设;
環(huán)境變量:
變量聲明和賦值:
declare -x NAME[=VALUE]
export NAME[=VALUE]
引用方式:
${NAME}, $NAME
注意:bash內(nèi)嵌了許多環(huán)境變量刁标,名稱為全大寫字母,例如UID址晕、HOME膀懈、PWD、SHELL, PATH, HISTSIZE等等谨垃;
環(huán)境變量查看:
export, declare -x
env, printenv
撤銷環(huán)境變量:
unset NAME
只讀變量:常量
(1) declare -r NAME
(2) readonly NAME
不支持重新賦值启搂,也不支持撤銷操作;
1 # declare -r username='whoami'
2 # echo $username
3 root
4 # unset username
5 -bash: unset: username: cannot unset: readonly variable
i刘陶、bash基于特性之九:I/O重定向和管道
程序的數(shù)據(jù)流有三個(gè):
輸入數(shù)據(jù)流: <–胳赌,標(biāo)準(zhǔn)輸入(stdin),鍵盤匙隔;
輸出數(shù)據(jù)流:–>匈织,標(biāo)準(zhǔn)輸出(stdout), 顯示器;
錯(cuò)誤數(shù)據(jù)流:–>牡直,錯(cuò)誤輸出(stderr)缀匕,顯示器;
fd:file descriptor碰逸,文件描述符乡小;
stdin: 0
stdout: 1
stderr: 2
IO重定向:
輸出重定向:
重定向程序正常執(zhí)行的結(jié)果
COMMAND > /PATH/TO/SOMEFILE
覆蓋重定向:覆蓋目標(biāo)文件中的原有內(nèi)容;
COMMAND >> /PATH/TO/SOMEFILE
追加重定向:追加新產(chǎn)生的內(nèi)容至目標(biāo)文件尾部饵史;
shell的一個(gè)功能開關(guān):
set -C
禁止覆蓋輸出重定向至已存在的文件满钟;
注意:此時(shí)仍然可以使用“>|”至目標(biāo)文件;
set +C
關(guān)閉上述特性胳喷;
錯(cuò)誤重定向:
重定向錯(cuò)誤的執(zhí)行結(jié)果湃番;
COMMAND 2> /PATH/TO/SOMEFILE
錯(cuò)誤輸出覆蓋重定向;
COMMAND 2>> /PATH/TO/SOMEFILE
錯(cuò)誤輸出追加重定向吭露;
合并標(biāo)準(zhǔn)輸出與錯(cuò)誤輸出流:
(1) &>, &>>
(2) COMMAND > /PATH/TO/SOMEFILE 2>&1
COMMAND >> /PATH/TO/SOMEFILE 2>&1
特殊輸出目標(biāo):/dev/null
位桶:bit bucket
特殊的輸入文件:/dev/zero
輸入重定向:
COMMAND < /PATH/FROM/SOMEFILE
tr命令:把輸出的數(shù)據(jù)當(dāng)中的字符吠撮,實(shí)現(xiàn)對(duì)位轉(zhuǎn)換,即把數(shù)據(jù)中的存在于字符集中的字符讲竿,統(tǒng)統(tǒng)轉(zhuǎn)換為字符集2中對(duì)應(yīng)的字符泥兰;
tr – translate or delete characters
tr [OPTION]… SET1 [SET2]
(1) tr SET1 SET2 < /PATH/FROM/SOMEFILE
字符轉(zhuǎn)換
1 # cat test
2 Hello World
3 # cat test |tr 'a-z' 'A-Z'
4 HELLO WORLD
(2) tr -d SET1 < /PATH/FROM/SOMEFILE
刪除
1 # cat test
2 Hello World
3 # cat test |tr -d 'ldH'
4 eo Wor
COMMAND << :
Here Document
用法:
COMMAND << EOF
COMMAND > /PATH/TO/SOMEFILE << EOF
管道:
COMMAND1 | COMMAND2 | COMMAND3 | …
練習(xí)1:把/etc/passwd文件最后三行信息中所有小寫字符改為大寫后輸出弄屡;
1 # tail -3 /etc/passwd|tr 'a-z' 'A-Z'
2 TEST1:X:5002:5002::/HOME/TEST1:/BIN/BASH
3 TEST2:X:5003:5003::/HOME/TEST2:/BIN/BASH
4 TEST3:X:5004:5004::/HOME/TEST3:/BIN/BASH
練習(xí)2:取出/etc/fstab的第6行;
1 # head -6 /etc/fstab |tail -1
2 # Accessible filesystems, by reference, are maintained under '/dev/disk'
練習(xí)3:取出/etc目錄下所有以p開頭的文件或目錄鞋诗,只顯示前5個(gè)膀捷;
1 # ls -d /etc/p*|head -5
2 /etc/pam.d
3 /etc/passwd
4 /etc/passwd-
5 /etc/pinforc
6 /etc/pkcs11
tee命令:
tee – read from standard input and write to standard output and files
tee [OPTION]… [FILE]…
-a:使用追加輸出,而非覆蓋削彬;
COMMAND | tee /PATH/TO/SOMEFILE
1 # cat test|tee /tmp/test.cat
2 Hello World
3 # cat /tmp/test.cat
4 Hello World
shell的展開
花括號(hào)展開
在非引號(hào)內(nèi)的內(nèi)容全庸,如果用花括號(hào)包括,而且里面用逗號(hào)分隔(至少包含一個(gè)逗號(hào)融痛,可以是空內(nèi)容)糕篇,這樣花括號(hào)里的內(nèi)容會(huì)被展開成用空格分開的一個(gè)列表,花括號(hào)前后可以緊隨前綴和后綴(前后綴都是可選的)酌心。
例如:
echo {a,b,c}
echo hello,{world,pig}
echo rep{,,,,,}eat
注意花括號(hào)展開,前綴不能是$挑豌,因?yàn)?{...}在shell中是變量
波浪號(hào)展開
從波浪號(hào)~到第一個(gè)未被引號(hào)包含的斜杠/(如果沒有斜杠安券,則全部算上),作為波浪號(hào)前綴氓英。
在波浪號(hào)后面的字符串作為一個(gè)可能的登錄名:如果為空侯勉,被展開成該用戶的HOME變量,如果HOME變量未設(shè)置铝阐,則用用戶執(zhí)行shell的主目錄替換址貌。如果不為空,則按照該登錄名的主目錄替換
例如:
echo ~ # 顯示$HOME內(nèi)容
HOME=/bin && echo ~ # 顯示/bin
unset HOME && echo ~ # 顯示當(dāng)前用戶主目錄
echo ~root # 顯示root用戶主目錄
波浪號(hào)還可以與加減號(hào)和數(shù)字徘键,產(chǎn)生一個(gè)遍歷文件夾堆棧的效果(關(guān)于文件夾堆棧练对,參考dirs、pushd吹害、popd幾個(gè)命令)螟凭。
echo ~+ # 顯示$PWD
echo ~- # 顯示$OLDPWD
echo ~+2 # 顯示dirs中第3個(gè)內(nèi)容,索引基于0
echo ~-3 # 顯示dirs中倒數(shù)第4個(gè)內(nèi)容它呀,索引基于0
如果無(wú)法展開螺男,那就會(huì)原樣顯示,例如dir堆棧中只有1個(gè)內(nèi)容纵穿,那么+1是無(wú)法展開的(這時(shí)只有+0有效)下隧。
Shell參數(shù)和變量展開
用$符號(hào)開始,后面接著變量名或者花括號(hào)括起來(lái)的變量名谓媒,如果是花括號(hào)內(nèi)以嘆號(hào)開頭淆院,那么就是變量名本身。
例如:
echo $PWD # 顯示PWD對(duì)應(yīng)的值
echo ${PWD} # 顯示PWD對(duì)應(yīng)的值
echo ${!PWD} # 顯示“PWD”這個(gè)變量名句惯,而不是它的值
echo ${!P*} # 顯示所有以P開頭的環(huán)境變量名
如果一個(gè)變量名不存在迫筑,就創(chuàng)建它宪赶。
echo ${HELLO:=hello} # 如果HELLO不存在,就用hello給它賦值脯燃,否則直接輸出$HELLO的值
算術(shù)展開
放在$(( ))中的表達(dá)式會(huì)被計(jì)算搂妻,其中變量會(huì)被求值,例如:
a=1 && b=3 && echo $(($a+$b))
如果是數(shù)字辕棚,0開頭的8進(jìn)制欲主,0x開頭的16進(jìn)制,其它進(jìn)制用Base#number的方式
可支持2~64進(jìn)制逝嚎,如果進(jìn)制小于等于36扁瓢,可以用a-z或A-Z表示10-35,如果進(jìn)制大于36补君,則a-z表示10-35引几,A-Z表示36-61,@表示62挽铁,表示63
例如:
echo $((16#32)) # 16進(jìn)制的32伟桅,輸出50
echo $((64#@)) # 輸出4031 = 62 * 64 + 63
用$[]也可以算術(shù)展開,但是不要和測(cè)試條件[]混淆了
例如:
echo $[1+4]
文件名展開
進(jìn)行字詞分隔后叽掘,如果不指定-f選項(xiàng)楣铁,shell會(huì)搜索"*","?"更扁,"["盖腕,如果遇到了,就會(huì)認(rèn)為是一個(gè)帶pattern的word浓镜,然后用字典序?qū)⒎系乃形募鎿Q過(guò)去溃列,如果沒有文件名匹配:1 shell的nullglob選項(xiàng)關(guān)閉,則不進(jìn)行文件名展開膛薛,保留word原樣哭廉;2 shell的nullglob打開,則移除這個(gè)word相叁。如果shell的nocaseglob選項(xiàng)打開遵绰,則忽略大小寫。
當(dāng)匹配文件名時(shí)(這里指不包括文件夾)增淹,除非shell的dotglob被設(shè)置椿访,否則.或./開頭的文件都必須顯示指定,例如:
ls * # 列出當(dāng)前文件夾中所有不以"."開頭的文件
ls .* # 列出當(dāng)前文件夾中所有以"."開頭的文件
當(dāng)匹配文件名時(shí)虑润,"/"必需顯示匹配成玫,例如:
ls ./* 和 ls .//是不同的。
其它情況下,"."和普通字符一樣哭当,例如:
.txt和txt都可以匹配a.txt
還有一個(gè)系統(tǒng)變量GLOBIGNORE猪腕,如果一個(gè)文件名匹配了一個(gè)pattern word,但是它也匹配了GLOBIGNORE钦勘,則它會(huì)被忽略陋葡,不過(guò)兩個(gè)特殊文件一定會(huì)被忽略,就是"."和".."彻采。
如果GLOBIGNORE打開腐缤,那么dotglob選項(xiàng)也會(huì)自動(dòng)打開,這樣會(huì)導(dǎo)致當(dāng)你ls 時(shí)肛响,其他以"."開頭的文件也會(huì)被match岭粤,如果想忽略"."開頭的文件,可以在GLOBIGNORE里面添加一個(gè)"."的匹配特笋。如果GLOBIGNORE未設(shè)定剃浇,則dotglob關(guān)閉。