10. BASH
type 查詢指令是否為Bash shell的內(nèi)建指令
結(jié)構(gòu):type [-tpa] name
常用參數(shù):
- -t: 不加任何參數(shù)跪者,type會顯示出name是外部指令還是bash內(nèi)建指令;加-t時陶珠,type會將name以底下這些字眼顯示出它的意義:file(外部指令)拴事,alias(別名設(shè)置的名稱)凌埂,builtin(bash內(nèi)建指令)
- -P: 如果后面接的name為外部指令時猖腕,才會顯示完整文件名;
- -a: 會有PATH變量定義的路徑中,將所含有name的指令都列出來硼瓣,包含alias
echo究飞,unset 變量的取用與設(shè)定
設(shè)置變量: key=value
取值: echo $key,key可以使用{}括起來堂鲤,建議采用這種方式
刪除變量: unset key
變量設(shè)定規(guī)則
1. 變量與變量內(nèi)容以一個等號來連接亿傅,等號兩邊不能直接接空格符,如『key = value』瘟栖;
2. 變量只能是英文字母與數(shù)字葵擎,但是不能以數(shù)字開頭;
3. 變量名中有空格或其他字符時可以使用『\』轉(zhuǎn)義或使用『"』,『'』將變量內(nèi)容結(jié)合起來半哟,這倆的區(qū)別是:
『var="lang is $LANG"』==>『echo $var』 ==>『lang is zh_TW.UTF-8』
『var='lang is $LANG'』==>『echo $var』 ==>『lang is $LANG』
4. 指令執(zhí)行中酬滤,如果需要其他額外的指令提供信息時签餐,可以使用反單引號『`指令`』或者『$(指令)』,列如:
『ls /lib/modules/$(uname -r)/kernel』
5. export key指令可以將key設(shè)置成環(huán)境變量盯串;
env氯檐,export,set
env 查看當(dāng)前環(huán)境變量体捏;
export不加任何參數(shù)冠摄,跟env一樣
set 查看所有變量,包含自定義的
特殊變量:
$: 關(guān)于本shell的PID
?: 上個指令的回傳值
OSTYPE,HOSTTYPE,MACHTYPE: 主機硬件與核心等級
如下圖:
export將自定義變量轉(zhuǎn)成是環(huán)境變量几缭,環(huán)境變量與普通變量差別在于『該變量是否會被“子程序”繼續(xù)使用』愚铡。
當(dāng)?shù)卿汱inux并取得一個bash之后椭盏,你的bash就是一個獨立的程序登钥,這個程序的識別使用程序標(biāo)識符谎砾,就是PID(echo $$),這個時候我們在這個bash底下執(zhí)行另一個bash韵洋,這個時候的界面就是新的bash,這個就是子程序黄锤,這個時候原bash就sleep了搪缨,需要exit或者logout才行,如圖:
原理
1. 當(dāng)啟動一個shell鸵熟,操作系統(tǒng)會分配一記憶區(qū)塊給shell使用副编,此內(nèi)存內(nèi)的變量可以讓子程序取用;
2. 若在父程序利用export功能流强,可以讓自定義變量的內(nèi)容寫到上述的記憶區(qū)塊當(dāng)中(環(huán)境變量)痹届;
3. 當(dāng)加載另一個shell時(啟動子程序),只shell可以將父shell的環(huán)境變量所在的記憶區(qū)塊導(dǎo)入自己的環(huán)境變量區(qū)塊當(dāng)中打月。
read队腐,array,declare/typeset
read
read [-pt] key
-p: 后邊可以接提示字符奏篙;
-t: 后邊接等待的秒數(shù)柴淘,時間到后會自動退出等待。
直接看圖:
declare / typeset
這倆指令是一樣的秘通,都是宣告變量類型为严,如果declare后不接任何參數(shù),效果相當(dāng)于set肺稀。
declare [-aixrp] key
-a: 將后邊名為key的變量定義成為數(shù)組(array)類型
-i: 將后面名為key的變量定義成為數(shù)字(integer)類型
-x: 用法與export一樣第股,就是將后邊的變量key變成環(huán)境變量,改成+x可以取消設(shè)置哦!
-r: 將變量設(shè)定成為 readonly 類型话原,該變量不可被更改夕吻,不能unset
-p: 單獨列出變量key诲锹,相當(dāng)于『export | grep key』
默認(rèn)定義變量為字符串類型,比如:
『declare sum=1+2+3』==>『sum=1+2+3』
『declare -i sum=1+2+3』==>『sum=6』
注意:bash環(huán)境中的數(shù)值運算梭冠,最多僅能達到整數(shù)形態(tài)辕狰,1/3=0!
數(shù)組設(shè)定方式
用法:var[index]=content
var[1]=name
var[2]=age
var[3]=sex
『echo "${var[1]},${var[2]},${var[3]}"』==>『name,age,sex』
如圖:
變量內(nèi)容的刪除控漠、取代與替換
刪除與取代
#:『從頭開始』蔓倍,刪除符合取代文字的『最短的』那一個
##:『從頭開始』,刪除符合取代文字的『最長的』那一個
%:『從尾開始』盐捷,刪除符合取代文字的『最短的』那一個
%%:『從尾開始』偶翅,刪除符合取代文字的『最長的』那一個
/oldStr/newStr: 把找到的『第一個』oldStr替換成newStr
//oldStr/newStr: 把找到的『所有』oldStr替換成newStr
變量設(shè)定方式 | 示例 | 操作 | 結(jié)果 |
---|---|---|---|
${變量#關(guān)鍵字} | m=/var/spool/mail/wangtao | echo ${m#/*/} | spool/mail/wangtao |
${變量##關(guān)鍵字} | m=/var/spool/mail/wangtao | echo ${m##/*/} | wangtao |
${變量%關(guān)鍵字} | m=/var/spool/mail/wangtao | echo ${m%/*} | /var/spool/mail |
${變量%%關(guān)鍵字} | m=/var/spool/mail/wangtao | echo ${m%%/*} | 空 |
${變量/oldchar/newchar} | m=/var/spool/mail/wangtao | echo ${m/o/R} | /var/spRol/mail/wangtao |
${變量//oldchar/newchar} | m=/var/spool/mail/wangtao | echo ${m//o/R} | /var/spRRl/mail/wangtaR |
操作演示
變量設(shè)定與替換(跟上面替換有區(qū)別哦!stderr=standard error output)
變量設(shè)定方式 | str沒有設(shè)定 | str為空字符串 | str已設(shè)定且非空 |
---|---|---|---|
var=${str-expr} | var=expr | var= | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var= | var=expr | var=expr |
var=${str:+expr} | var | var= | var=expr |
var=${str=expr} | str=expr;var=expr | str不變;var= | str不變;var=$str |
var=${str:=expr} | str=expr;var=expr | str=expr;var=expr | str不變;var=$str |
var=${str?expr} | expr輸出至stderr | var= | var=$str |
var=${str:?expr} | expr輸出至stderr | expr輸出至stderr | var=$str |
alias碉渡,unalias聚谁,history別名的設(shè)定和歷史指令
alias和unalias
別名的使用很簡單,就是把一些指令加上一些參數(shù)滞诺,取個別名形导,以后就用別名來執(zhí)行這個指令;
通過alias指令不加任何參數(shù)就可以看到已經(jīng)設(shè)置的哪些別名习霹。
unalias當(dāng)然就是取消別名的設(shè)置;
alias lm='ls -lh'
unalisa lm
如圖所示:
history
歷史指令可以查詢當(dāng)前登錄用戶執(zhí)行指令的歷史記錄朵耕,默認(rèn)最大記錄為1000條,可用過環(huán)境變量$HISTSIZE查看或更改淋叶。
history [n]
history [-nc]
history [-raw] [histfiles]
n: n為數(shù)字阎曹,意思是列出最近n條歷史記錄;
-c: 將目前shell中的歷史記錄全部清除煞檩;
-a: 將目前新增的history指令新增入histfiles當(dāng)中处嫌;
-r: 將histfiles的內(nèi)容讀到當(dāng)前這個shell的history記憶中;
-w: 將目前shell的history寫入到histfiles中斟湃,注銷時也會自動寫入histfiles中熏迹;
注意: 若沒有histfiles,則都會讀取或?qū)懭腩A(yù)設(shè)~/.bash_history中凝赛,環(huán)境變量$HISTFILE;
!!癣缅,!number,!command
!!: 執(zhí)行上一條歷史指令哄酝;
!number: 執(zhí)行第number條歷史記錄指令友存,number在history指令的輸出中有每一行的最前面;
!command: 執(zhí)行歷史記錄中開頭為command的指令陶衅;
有圖有真相:
Bash shell的操作環(huán)境
命令下達時指令的查找順序
1. 以相對/絕對路徑執(zhí)行指令屡立,列如 /bin/ls 或 ./ls;
2. 由 alias 找到該指令來執(zhí)行;
3. 由bash內(nèi)建的(builtin)指令來執(zhí)行;
4. 透過 $PATH 這個變量的順序搜尋到的第一個指令來執(zhí)行膨俐。
如上圖所示:
我們給『echo $MAIL』這條指令取了個別名『echo』勇皇;
接下來我們執(zhí)行『type -a echo』來查看執(zhí)行結(jié)果;
可以看到指令先通過alias找到了指令『echo $MAIL』;
然后再到內(nèi)建指令builtin焚刺;
最后找到『/usr/bin/echo』敛摘。
login shell 和 non-login shell
login shell: 取得bash時需要完整的登錄流程的;
non-login shell: 不需要輸入用戶名密碼就取得的shell乳愉,比如我等使用兄淫;
比如:我們輸入用戶名密碼登陸后取得的shell,就是login shell蔓姚,然后我們再在這個shell中使用bash指令捕虽,這個時候這個子程序的bash是沒有輸入用戶名密碼進入的,這個子程序的bash就叫non-login shell坡脐。
讀取的配置文件
login shell:
1. /etc/profile: 該文件會去調(diào)用并讀取其他目錄下的文件(/etc/profile.d/*)泄私,具體看后邊的讀取流程圖;
2. ~/.bash_profile,~/bash_login,~/.profile:這三個文件只會讀取其中的一個备闲,優(yōu)先級順序就是寫的順序晌端,先遇到誰就讀誰;
non-login shell恬砂,centos7.x還會呼叫/etc/bashrc哦咧纠;
1. 也會讀取/etc/profile,但是此時/etc/profile中會根據(jù)權(quán)限確定是否讀取/etc/profile.d/*中的某些內(nèi)容;
2. 讀取~/.bashrc
source(.)
source指令為讀入環(huán)境配置文件的指令,可以用一個小數(shù)點『.』來代替該指令觉既。
source /etc/profile <==> . /etc/profile
終端機的環(huán)境設(shè)定stty,set
主要是設(shè)置中昂端機tty1-6的一些環(huán)境參數(shù)乳幸,不演示了瞪讼,用到的時候自行man page或者百度。
數(shù)據(jù)流重導(dǎo)向<,<<,>,>>
數(shù)據(jù)傳輸情況如圖
1. 標(biāo)準(zhǔn)輸入 stdin: 代碼為 0 粹断,使用 < 或 << 符欠;
2. 標(biāo)準(zhǔn)輸出 stdout: 代碼為 1 ,使用 > 或 >> 或 1> 或 1>> 瓶埋;
3. 標(biāo)準(zhǔn)錯誤輸出 stderr: 代碼為 2 希柿,使用 2> 或 2>> 。
指令 > 和 >>
1>: 以『覆蓋』的方式將『正確的數(shù)據(jù)』輸出到指定的文件或裝置上养筒;
1>>: 以『累加』的方式將『正確的數(shù)據(jù)』輸出到指定的文件或裝置上曾撤;
2>: 以『覆蓋』的方式將『錯誤的數(shù)據(jù)』輸出到指定的文件或裝置上;
2>>: 以『累加』的方式將『錯誤的數(shù)據(jù)』輸出到指定的文件或裝置上晕粪;
find /home /root -name .bashrc > list_right 2>list_error
查詢/home,/root目錄下名字是.bashrc的文件挤悉,并輸出到list_right文件中,錯誤信息輸出到list_error文件中
/dev/null 垃圾桶黑洞巫湘,能把所有輸入到這里頭的東西吃掉
我們現(xiàn)在只要正確信息装悲,錯誤信息丟棄昏鹃,直接輸出到垃圾黑洞,如圖:
我們知道 > 是將stdout重導(dǎo)向到一個地方诀诊,那么我們怎么把錯誤信息也導(dǎo)向同樣的地方呢洞渤?這個時候就需要使用 & 了;以下三種寫法都對属瓣,很簡單吧载迄,一看就明白了吧!
find /name /root -name .bashrc > list_right 2>&1
find /name /root -name .bashrc 2> list_right 1>&2
find /name /root -name .bashrc &> list_right
如果我們不想讓文件內(nèi)容被覆蓋怎么辦奠涌?那當(dāng)然是使用 >> 追加到文件末尾咯
指令 < 和 <<
采用cat創(chuàng)建新文件宪巨,手動輸入,ctrl+d結(jié)束溜畅,文件存在時會直接覆蓋掉捏卓!
手動輸入也很麻煩,可以使用stdin慈格,就是 < 咯怠晴,文件存在時會直接覆蓋掉!
將剛創(chuàng)建的list_right文件的內(nèi)容輸出到newfile當(dāng)中
手動輸入浴捆,并以 "eof" 字符結(jié)束蒜田,不使用ctrl+d,從下圖中可以看到最后的結(jié)束符eof是不會寫入文件的选泻,當(dāng)然 << 的用法遠(yuǎn)不止這個冲粤。
指令執(zhí)行的判斷依據(jù)『$?』,『;』,『&&』,『||』
連續(xù)執(zhí)行多條指令『;』
比如同時想打開/root和/home倆文件夾,ls /root ; ls /home
$?页眯,&&梯捕,||
&& 和 || 會依靠指令的回傳值$0
指令下達情況 | 說明 |
---|---|
cmd1&&cmd2 | 若cmd1執(zhí)行完畢且正確執(zhí)行($?=0),則執(zhí)行cmd2;否則不執(zhí)行cmd2 |
cmd1||cmd2 | 若cmd1執(zhí)行完畢且正確執(zhí)行窝撵,則不執(zhí)行cmd2傀顾,否則執(zhí)行cmd2 |
簡單示例,查閱目錄~/test是否存在碌奉,如果存在就建立文件~/test/hehe
從圖中可以看到第一次文件夾不存在直接輸出了異常短曾,后邊指令不執(zhí)行;
當(dāng)我們新建了文件夾test之后赐劣,前面指令執(zhí)行成功嫉拐,于是建立了新文件;
判斷文件夾~/tt是否存在魁兼,如果不存在就新建該文件夾
可于看到我們前面的指令執(zhí)行報錯了椭岩,文件夾不存在,于是執(zhí)行了后面的指令,建立了新文件夾判哥。
仔細(xì)觀察下面這倆例子
無論~/test是否存在献雅,都要建立~/test/hehe這個文件咋辦?
如果~/aaa存在就輸出exsit塌计,如果不存在就輸出not exsit挺身;
ls ~/test || mkdir ~/test && touch ~/test/hehe
ls ~/aaa && echo "exsit" || echo "not exsit"
最后附上指令依序執(zhí)行的關(guān)系示意圖
管線命令(pipe)|
管線命令僅會處理stdout,對于stderr會忽略(可以通過2>&1來吧stderr轉(zhuǎn)成stdout哦锌仅!)
管線命令必須要能夠接受來自前一個指令的數(shù)據(jù)成為stdin繼續(xù)處理才行章钾。
經(jīng)典示例
仔細(xì)觀察圖中的四條指令,我們ll bb指令會產(chǎn)生stderr热芹。
1. 第一次執(zhí)行的時候我們看到屏幕上輸出了含有such字樣的行(理論上不應(yīng)該出來贱傀,對吧,因為我們grep -v查找的是不含such的行伊脓,繼續(xù)看后面)府寒;
2. 第二條指令我們也查詢不含such的行,我們使用 2>&1 把stderr輸出到stdout,這個時候我們看到屏幕上并沒有任何輸出(看樣子這條指令應(yīng)該是對了报腔,繼續(xù)往下看)株搔;
3. 第三條指令我們查詢含有such字樣的行,我們發(fā)現(xiàn)屏幕上輸出了一行含有such的行(咋一看好像對了纯蛾,但是好像跟pipe只接受stdout有點沖突纤房,繼續(xù)看后面);
4. 第四條指令將stderr輸出到stdout翻诉,然后我們依然查詢含有such字樣的行炮姨,看到了吧,屏幕同樣輸出了含有such的行碰煌,但是這個時候such是高亮的J姘丁!V舨椤吁津;
明白了吧E镄睢6榉觥!
第一條指令執(zhí)行的時候梭依,由于pipe只接受stdout稍算,所以stderr會輸出到屏幕,它并沒有進入管道役拴,就像『find /root /home ./bash > list_right』錯誤輸出會輸出到屏幕糊探,而不會進入文件list_right一樣;
第二條指令因為將stderr轉(zhuǎn)成了stdout,所以他進入了管道科平,而我們查找的是不含such的行褥紫,所以沒有任何輸出;
第三條指令跟第一條指令一樣瞪慧,同樣是沒有進入管到髓考,只是輸出了stderr在屏幕而已;
第四條指令因為將stderr轉(zhuǎn)成了stdout弃酌,進入了管道氨菇,所以在查詢憨厚such字樣的時候,該行被查到了妓湘,所以屏幕上輸出來了查蓉,并且?guī)в懈吡溜@示!
cut榜贴,grep截取命令
cut
cut -d '分割字符' -f 分割后字符序號
cut -c 字符區(qū)間
-d: 后邊跟分割字符豌研,與-f一起使用;
-f: 依據(jù)-d分割出來的字段竣灌,用-f取出那幾段聂沙;
-c: 義字符的單位取出固定的字符區(qū)間,12-表示取出第12個字符后的所有字符初嘹,12-20表示取出第12-20個字符及汉;
grep
grep [-acinvABC] [--color=auto] 'keyword' filename
-a: 將binary文件以text文件的方式搜索數(shù)據(jù);
-c: 計算找到'keyword'的次數(shù)屯烦;
-i: 忽略大小寫坷随;
-n: 輸出行號;
-v: 反向選擇驻龟,即輸出沒有'keyword'的行温眉;
-[ABC] number: number是數(shù)字,表示將keword所在行的后([A]fter)number行也輸出 翁狐,前([B]efore)number行也輸出类溢,前后([C])number行也輸出;
--colr=auto: 將找到的關(guān)鍵字加上顏色顯示露懒。
sort闯冷,wc,uniq排序統(tǒng)計去重指令
sort
sort [-fbmnrtuk] [file or stdin]
-f: 忽略大小寫懈词;
-b: 回了最前面的空格蛇耀;
-M: 一月份的名字來排序,JAN,DEC等排序方法;
-n: 使用村數(shù)字來排序坎弯;
-r: 反向排序纺涤;
-u: 就是uniq译暂,相同的數(shù)據(jù)中,僅出現(xiàn)一行撩炊;
-t: 分隔符外永,預(yù)設(shè)使用[tab]來分割;
-k: 以那個區(qū)間(field)來排序拧咳;
如圖:
uniq
uniq [-ic]
-i: 忽略大小寫象迎;
-c: 進行統(tǒng)計,統(tǒng)計的數(shù)量會在每一行最前面呛踊,注意這個不是行號砾淌;
注意:這個去重是指將重復(fù)的東西減少,所有必須要配合排序使用咯谭网,看圖吧
wc
wc [-lwm]
-l: 僅統(tǒng)計行數(shù)汪厨;
-w: 僅統(tǒng)計單詞數(shù)(英文單詞);
-m: 僅統(tǒng)計所有字符愉择;
不加任何參數(shù)時三個一起統(tǒng)計劫乱,有圖有真相:
tee 雙重重導(dǎo)向
由于 > 會將數(shù)據(jù)流整個傳送給文件或裝置,因此除非我們?nèi)プx取文件或裝置锥涕,否則就無法繼續(xù)利用這個數(shù)據(jù)流衷戈;tee的作用就是將處理過程中的某段訊息存下來,并且讓數(shù)據(jù)流繼續(xù)往后流動层坠。
tee數(shù)據(jù)流示意圖
tee [-a] file
-a: 以累加的方式殖妇,將數(shù)據(jù)寫入file當(dāng)中
tr,col,join,paste,expand字符轉(zhuǎn)換命令
tr 可以用來刪除一段訊息當(dāng)中的文字,或者是進行文字訊息的替換
tr [-ds] SET1 ...
-d: 刪除訊息當(dāng)中的SET1這個字符串破花,tr [0-9]刪除所有數(shù)字谦趣;
-s: 取代掉重復(fù)的字符,-s可以省略座每,tr [a-z] [A-Z]前鹅,把字符全部換成大寫.
有圖有真相:
col,join,paste,extend就自己man page吧!
split 文件分割命令
當(dāng)文件很大時峭梳,可以根據(jù)問價你大小或行數(shù)來將其分割成小文件舰绘。
split [-bl] file PREFIX
-b: 后邊可以接欲分割成的文件大小,可加單位b葱椭,k捂寿,m等;
-l: 以行數(shù)來進行分區(qū)挫以;
PREFIX: 作為分區(qū)文件的前綴者蠕;
有圖有真相:
xargs 參數(shù)代換
x 加減乘除的乘號窃祝,args就是argumens(參數(shù))的意思掐松;這貨的作用就是產(chǎn)生某個指令的參數(shù)的意思踱侣;它可以讀入stdin的數(shù)據(jù),并且以空格符或斷行字符作為分辨大磺,將stdin分割成aguments抡句;因為是以空格作為分割,所以當(dāng)一些檔名或者其他意義的名詞含有空格符的時候杠愧,就會造成誤判哦待榔。
xargs [-0epn] command
-0: 如果stdin含有特殊字符,這個參數(shù)可以將其還原成一般字符流济,這個參數(shù)可以用于特殊狀態(tài)锐锣;
-e: EOF(end of file)的意思,后邊可以接一個字符串绳瘟,當(dāng)xargs分析到這個字符串時雕憔,就停止;
-p: 再執(zhí)行每個指令的argument時糖声,都會詢問使用者斤彼;
-n: 后面接次數(shù),每次command指令執(zhí)行時使用幾個參數(shù)蘸泻。
如圖所示:『cut -d ':' -f 1 /etc/passwd | head -n 3 |xargs -n 1 id』琉苇;
id指令每次只能接受一個參數(shù),用來查詢用戶的uid悦施,gid等信息并扇;我們查詢/etc/passwd里面的前三條數(shù)據(jù),取出名字抡诞,通過xargs一個一個傳給id進行處理拜马;
注意: 很多指令不支持管線管道命令,我們也可以通過xargs來提供這些指令引用stdin哦沐绒!
- 減號的用途
在管道命令中俩莽,常常會使用到前一個指令的stdout來作為這次的stdin,某些命令需要用到文件名(例如tar)來進行處理是乔遮,改stdin與stdout可以用減號拉代替:
如圖所示:『tar -cvf - aaa/ | tar -xvf - -C bbb/』;
這條指令的意思是:將aaa文件夾打包扮超,但是打包的數(shù)據(jù)不是記錄到文件(tar的-f后邊跟的是文件名哦,忘記了嗎蹋肮?)出刷,而是傳送到stdout;經(jīng)過管道后坯辩,將tar -cvf aaa/傳送給后面的tar -xvf;
后面這個 - 則是取用前一個指令的stdout馁龟,因此我們就不需要filename了!很騷哦~
over...