1.管線命令(pipe)
學(xué)習(xí)正規(guī)表示法之前,讓我們先了解一下管線命令(pipe)。
1.1 獲取命令:cut、grep
cut
功能簡(jiǎn)介:
[~]$ cut -d "分割字符" -f fields
[~]$ cut -c 字符區(qū)間
選項(xiàng)與參數(shù):
-d :后面加分割字符。與-f一起只用;
-f :依據(jù)-d的分割字符將一段訊息分區(qū)為數(shù)段,用-f是取出第幾段的意思;
-c :以字符的單位取出固定字符區(qū)間;
示例1:將PATH變量取出,找出第3個(gè)路徑
[~]$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Frameworks/Python.framework/Versions/3.7/bin:/usr/local/mysql/bin
[~]$ echo $PATH | cut -d ":" -f 3 ##如果取多個(gè)路徑用","分割
示例2:將export輸出的訊息,取得第12字符以后的所有字符串
[~]$ export | cut -c 12-
示例3:用last將顯示的登入者的信息,僅留下用戶名
[~]$ last | cut -d ' ' -f 1
grep
cut是將一行訊息取出某部分我們想要的,而grep則是分析一行訊息,若當(dāng)中有我們需要的,就將該行取出來。
功能簡(jiǎn)介:
[~]$ grep [-acinv] [--color=auto] '字符串' filename
選項(xiàng)與參數(shù):
-a :將binary文件以text文件的方式搜索數(shù)據(jù);
-c :計(jì)算找到"字符串"的次數(shù);
-i :忽略大小寫;
-n :順便輸出行號(hào);
-v :反向選擇,即顯示出沒有"字符串"內(nèi)容的那一行;
--color=auto :可以將找到的關(guān)鍵詞部分加上顏色顯示;
示例1:將last中,有出現(xiàn)root的行取出來;
[~]$ last |grep 'root'
示例2:與示例1相反,只要沒有root的就取出;
[~]$ last |grep -v 'root'
示例3:在last中,只要有root就取出且僅取出第一行;
[~]$ last |grep 'root' |cut -d ' ' -f 1
示例4:取出/etc/man_db.conf內(nèi)包涵MANPATH的那幾行;
[~]$ grep --color=auto 'MANPATH' /etc/man.conf
1.2 排序指令:sort、wc、uniq
sort
如果想對(duì)數(shù)據(jù)排序怎么做呢?
功能簡(jiǎn)介:
[~]$ sort [-fbMnrtuk] [file or stdin]
選項(xiàng)與參數(shù):
-f :忽略大小寫;
-b :忽略最前面的空格符部分;
-M :以月份的名字來排序,例如JAN、DEC等;
-n :使用純數(shù)字進(jìn)行排序,默認(rèn)是以文字形態(tài)來排序的;
-r :反向排序;
-u :就是uniq,相同的數(shù)據(jù),僅出現(xiàn)一行代表;
-t :分隔符,默認(rèn)是用[tab]鍵來分隔的;
-k :以那個(gè)區(qū)間來進(jìn)行排序;
示例1:將/etc/passwd中個(gè)人賬號(hào)排序
[~]$ cat /etc/passwd | sort
示例2:/etc/passwd內(nèi)容是以:來分隔的,想以第三欄來排序
[~]$ cat /etc/passwd | sort -t ':' -k 3 nobody [-n 讓它使用數(shù)字排序]
示例3:last中,輸出的數(shù)據(jù)僅取賬號(hào),并加以排序
[~]$ last | cut -d ' ' -f 1 |sort
uniq
如果想去重怎么做?
功能簡(jiǎn)介:
[~]$ uniq [-ic]
選項(xiàng)參數(shù):
-i :忽略大小寫字符的不同;
-c :進(jìn)行計(jì)數(shù);
示例1:使用last將賬號(hào)列出,僅取出賬號(hào)列,進(jìn)行排序后去重;
[~]$ last | cut -d ' ' -f 1 |sort |uniq
示例2:接上例,如果還想知道每個(gè)人的登入次數(shù)呢?
[~]$ last | cut -d ' ' -f 1 |sort |uniq -c
wc
如果我想知道/etc/passwd/man_db.conf文件有多少字,多少行怎么做?
功能簡(jiǎn)介:
[~]$ wc [-lwm]
選項(xiàng)與參數(shù):
-l :僅列出行;
-w :僅列出多少字(英文單字);
-m :多少字符;
示例1:/etc/man_db.conf里面有多少相關(guān)字、行、字符數(shù)?
[~]$ cat /etc/man_db.conf | wc
140 720 4574 ##輸出的分別代表:行、字?jǐn)?shù)、字符數(shù)
示例2:last可以輸出登入者,但是last最后兩行并非賬號(hào)內(nèi)容,該如何以一行指令串取出登入系統(tǒng)的總?cè)藬?shù)?
[~]$ last | grep [a-zA-Z] | grep -v 'wtmp' | grep -v 'reboot' |grep -v 'unkown' |grep -v 'shutdown'|wc -l
1.3 雙向重導(dǎo)向:tee
">" 標(biāo)記會(huì)將數(shù)據(jù)流整個(gè)傳送給文件或裝置,因此我們必須去讀取這個(gè)文件或裝置。如果想要從這個(gè)數(shù)據(jù)流處理過程中獲取某段數(shù)據(jù)該怎么做?
tee會(huì)同時(shí)將數(shù)據(jù)流分送到文件和屏幕,輸出到屏幕的我們叫它"stdout"。
功能簡(jiǎn)介:
[~]$ tee [-a] file
選項(xiàng)與參數(shù):
-a :以累加的方式,將數(shù)據(jù)加入file中。
示例1:將last的輸出存到last.list中
[~]$ last | tee last.list
示例2:將ls的數(shù)據(jù)保存一份到ls.txt中,同時(shí)屏幕也有輸出信息。
[~]$ ls -l | tee ls.txt |more
1.4 字符轉(zhuǎn)換命令:tr、col、join、paste、expand
tr
tr可以刪除一段數(shù)據(jù)中的文字,或者進(jìn)行文字的替換
功能簡(jiǎn)介:
[~]$ tr [-ds] SET1 ...
選項(xiàng)與參數(shù):
-d :刪除數(shù)據(jù)中SET1的這個(gè)字符串;
-s :去重;
示例1:將last輸出的數(shù)據(jù),所有的小寫編程大寫;
[~]$ last |tr '[a-z]' '[A-Z]'
示例2:將/etc/passwd輸出的數(shù)據(jù),將冒號(hào)去掉;
[~]$ cat /etc/passwd | tr -d ':'
col
功能簡(jiǎn)介:
[~]$ col [-xb]
選項(xiàng)與參數(shù):
-x :將tab鍵轉(zhuǎn)換成對(duì)等的空格鍵
示例1:利用cat -A顯示所有的特殊按鍵,以col將tab鍵轉(zhuǎn)成空格鍵
[~]$ cat /etc/man.conf |col -x |cat -A
join
它表示處理兩個(gè)文件之間的數(shù)據(jù),主要在處理"兩個(gè)文件中,有相同數(shù)據(jù)的那一行,才將它加在一起"。
功能簡(jiǎn)介:
[~]$ join [-til2] file1 file2
選項(xiàng)與參數(shù):
-t :join默認(rèn)以空格符分隔數(shù)據(jù),并且比對(duì)第一個(gè)字段的數(shù)據(jù),如果兩個(gè)文件相同,則將兩筆數(shù)據(jù)連成一行,且第一個(gè)字段放在第一個(gè);
-i :忽略大小寫;
-1:后面加數(shù)字,代表第一個(gè)文件要用第幾個(gè)字段來分析;
-2:后面加數(shù)字,代表第二個(gè)文件要用第幾個(gè)字段來分析;
示例1:將/etc/passwd與/etc/shadow相關(guān)數(shù)據(jù)整合成一欄
[~]$ head -n 3 /etc/passwd /etc/shadow ##可以看到這兩個(gè)文件的最左邊字段是相同的賬號(hào),并且以 :分割
[~]$ join -t ':' /etc/passwd /etc/shadow | head -n 3 ##相同的部分被移動(dòng)到最前面了
示例2:/etc/passwd第四個(gè)字段是GID,/etc/group第三個(gè)字段是GID,怎么樣整合?
[~]$ head -n 3 /etc/passwd /etc/group ## 他們中的第四個(gè)和第三個(gè)"0"則表示GID
[~]$ join - t ':' -1 4 /etc/passwd -2 3 /etc/group | head -n 3 ##相同的字段部分被移動(dòng)到最前面了
注意:在使用join之前,你需要處理的文件應(yīng)該要事先經(jīng)過排序(sort)處理。否則,有些比對(duì)的會(huì)被略過。
paste
paste:"將兩行貼在一起,中間以tab鍵隔開"。
功能簡(jiǎn)介:
[~]$ paste [-d] file1 file2
選項(xiàng)與參數(shù):
-d :后面接分割字符,預(yù)設(shè)是以tab鍵來分割;
- :如果file部分寫成 - ,表示來自stdin的意思;
示例1:將/etc/passwd與/etc/shadow同一行貼在一起
[~]$ paste /etc/passwd /etc/shadow
示例2:先將/etc/group讀出,然后與示例1貼在一起,僅取出前三行
[~]$ cat /etc/group | paste /etc/passwd /etc/shadow - | head -n 3 ##這個(gè)例子重點(diǎn)在 - 的使用,表示stdin
expand
expand:將tab鍵轉(zhuǎn)成空格鍵。
功能簡(jiǎn)介:
[~]$ expand [-t] file
選項(xiàng)與參數(shù):
-t :后面加數(shù)字。定義一個(gè)tab鍵代表多少個(gè)空格鍵。
示例1:將/etc/man_db.conf行首是MANPATH的行就取出,僅取前三行;
[~]$ grep '^MANPATH' /etc/man_db.conf |head -n 3 ##行首的標(biāo)志為^
示例2:接示例1,如果想要將所有的符號(hào)都取出來?
[~]$ grep 'MANPATH' /etc/man.conf |head -n 3 |cat -A ##cat -A 可以把所有的tab鍵顯示為^I
示例3:接示例2,怎樣將tab鍵設(shè)定代表為6個(gè)空格字符?
[~]$ grep 'MANPATH' /etc/man.conf |head -n 3 |expand -t 6 |cat -A ##expand將tab轉(zhuǎn)成空格,所以cat -A查看不到了
1.5 分區(qū)命令:split
split:可以將一個(gè)大文件依據(jù)文件大小或行數(shù)來分區(qū),就可以將大文件分區(qū)為小文件了。
功能簡(jiǎn)介:
[~]$ split [-bl] file PREFIX
選項(xiàng)與參數(shù):
-b :后面加想分區(qū)成的文件大小,可以加單位,例如b,k,m等;
-l :以行數(shù)來進(jìn)行分區(qū)
PREFIX :代表前導(dǎo)符,可作文分區(qū)文件的前導(dǎo)文字
示例1: /etc/services 有600kb,怎么分成300kb一個(gè)文件?
[~]$ split -b 300k /etc/services services
[~]$ ll -k services* ##可以看到被分成了servicesaa,servicesab,servicesac,services就是前導(dǎo)向名字了。
示例2:如何將上面3個(gè)小文件合成一個(gè)文件,檔名為servicesback?
[~]$ cat services* >> servicesback
示例3:將ls -al / 輸出的信息,每十行記錄成一個(gè)文件;
[~]$ ls -al / | split -l 10 - lsroot ## 重點(diǎn)是 - ,它表示stdout或stdin。
1.6 參數(shù)替換: xargs
xargs : x是加減乘除的乘號(hào),就是在產(chǎn)生某個(gè)指令的參數(shù)的意思。
功能簡(jiǎn)介:
[~]$ xargs [0epn] command
選項(xiàng)與參數(shù):
-0 :如果輸入的stdin含有特殊字符,例如`,\,空格鍵等,-0可以將它還原成一般字符。
-e :這個(gè)是EOF(end of file)的意思。后面加一個(gè)字符串,和字符串中間不沒有空格鍵的,當(dāng)xargs分析到這個(gè)字符串時(shí)會(huì)停止繼續(xù)工作。
-p :在執(zhí)行每個(gè)指令的argument時(shí),都會(huì)詢問使用者。
-n :后面加次數(shù),每次command指令執(zhí)行時(shí),指定要使用幾個(gè)參數(shù)。
示例1:將/etc/passwd內(nèi)的第一列取出,僅取三行,使用id將每個(gè)賬號(hào)內(nèi)容顯示出來
[~]$ id root ## 這個(gè)id可以查詢用戶的UID/GID等
[~]$ id $(cut -d ':' -f 1 /etc/passwd | head -n 3) ## $(cmd)可以預(yù)先取得參數(shù),但id只能接受一個(gè)參數(shù),上述指令會(huì)執(zhí)行錯(cuò)誤
[~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | id ## id并不是管道命令,此命令執(zhí)行后,只會(huì)執(zhí)行id
[~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs id ##依舊是錯(cuò)誤,因?yàn)閤args一口氣將全部的數(shù)據(jù)都給id處理,但是id只能接受1個(gè)參數(shù)。
[~]$ cut -d ':' -f 1 /etc/passwd | head -n 3 | xargs -n 1 id
1.7 減號(hào)的用途
在管道命令中,嘗嘗會(huì)使用到前一個(gè)指令的stdout作為這次的stdin,例如下面的例子:
[~]$ tar -cvf - /home | tar -xvf - -C /tmp/homeback ## 將/home里面的文件打包,但打包的數(shù)據(jù)不記錄到文件而是傳送到stdout,經(jīng)過管道后,傳送給后面的 - 。
2.正規(guī)表示法
2.1什么是正規(guī)表示法?
簡(jiǎn)單來說,正規(guī)表示法就是處理字符串的方法,他是以行為單位進(jìn)行字符串處理的行為,正規(guī)表示法通過一些特殊符號(hào)的輔助,可以讓使用者對(duì)某些特定字符串進(jìn)行搜索、刪除、取代的處理。
它有基礎(chǔ)正規(guī)表示法和延伸表示法。延伸表示法就是除了一些簡(jiǎn)單的操作,還可以以群組的字符串處理。例如:對(duì)Wechat和QQ字符串的搜索,注意是OR的關(guān)系而不是AND的關(guān)系。
2.2 基礎(chǔ)正規(guī)表示法
正規(guī)表示法是處理字符串的一種表示方式,那么對(duì)字符排序有影響的語系就會(huì)對(duì)正規(guī)表示法的結(jié)果產(chǎn)生影響了。
語系對(duì)正規(guī)表示法的影響
為什么語系會(huì)影響正規(guī)表示法的輸出結(jié)果?因?yàn)椴煌Z系的編碼數(shù)據(jù)是不同的,例如下面的例子:
LANG=C :0 1 2 ... A B C ... a b c ...
LANG=zh_TW :0 1 2 ... a A b ... z Z
所以使用正規(guī)表示法時(shí),需要特別留意當(dāng)時(shí)環(huán)境的語系,否則可能會(huì)發(fā)現(xiàn)與別人不同的搜索結(jié)果。
下面的練習(xí)使用"LANG=C"這個(gè)語系。 為了避免這個(gè)編碼造成的英文與數(shù)字的獲取問題,有些特殊符號(hào)我們也應(yīng)該了解一下:
[:alnum:] :表示英文大小寫字符及數(shù)字,即0-9,A-Z,a-z;
[:alpha:] :表示任何英文大小寫字符,即A-Z,a-z;
[:blank:] :表示空格鍵和[tab]按鍵;
[:cntrl:] :表示鍵盤上的控制按鍵,即CR、LF、Tab、Del等等;
[:digit:] :表示數(shù)字0-9;
[:graph:] :表示除了空格鍵與[Tab]外的其他所有按鍵;
[:lower:] :表示小寫字符,即a-z;
[:upper:] :表示大寫字符,即A-Z;
[:print:] :表示任何可以被打印出來的字符;
[:punct:] :表示標(biāo)點(diǎn)符號(hào),即:" ' ? ! # $ 等等;
[:space:] :表示任何會(huì)產(chǎn)生空白的字符,包括空格、[Tab]、CR等;
[:xdigit:] :表示16進(jìn)制的數(shù)字類型,因此包括0-9,A-F,a-f;
2.3 grep的一些進(jìn)階選項(xiàng)
[~]$ grep [-A] [-B] [--color=auto] '搜索字符串' filename
選項(xiàng)與參數(shù):
-A :后面加數(shù)字,為after的意思,除了列出該行外,后續(xù)的n行也列出來;
-B :后面加數(shù)字,為before的意思,除了列出改行外,前面的n行也列出來;
--color=auto :將要搜索的字符串附加顏色;
2.4 基礎(chǔ)正規(guī)表示法練習(xí)
假設(shè)有以下文件:
[~]$ vi regular_express.txt
"Open Source" is a good mechanism to develop programs.
apple is my favorite food.
Football game is not use feet only.
this dress doesn't fit me.
However, this dress is about $ 3183 dollars.
GNU is free air not free beer.
Her hair is very beauty.
I can't finish the test.
Oh! The soup taste good.
motorcycle is cheap than car.
This window is clear.
the symbol '*' is represented as start.
Oh! My god!
The gd software is a library for drafting programs.
You are the best is mean you are the no. 1.
The world <Happy> is the same with "glad".
I like dog.
google is the best tools for search keyword.
goooooogle yes!
go! go! Let's go.
# I am VBird
示例1:搜索指定字符串
[~]$ grep -n 'the' regular_express.txt --color=auto
示例2:利用中括號(hào)來搜索集合字符
如果想要搜索"test"和"taste"兩個(gè)關(guān)鍵字,我們可以這樣來搜索:
[~]$ grep -n '[tae]st' regular_express.txt --color=auto
如果我們想搜索"oo",但不想要前面有"g"的數(shù)據(jù)怎么做?可以在集合字符中使用反向選擇"[^]":
[~]$ grep -n '[^g]oo' regular_express.txt --color=auto
如果"oo"前不想要小寫字符,可以這樣寫:
[~]$ grep -n '[^a-z]oo' regular_express.txt --color=auto
如果字符組是連續(xù)的,例如大寫/小寫/數(shù)字等等,就可以使用"[a-zA-Z0-9]"來表示。
由于語系對(duì)編碼順序是有影響的,因此也可以使用下面的表示法來測(cè)試前面的結(jié)果:
[~]$ grep -n '[^[:lower:]]oo' regular_express.txt --color=auto
[~]$ grep -n '[[:digit:]]' regular_express.txt --color=auto
示例3:行首與行尾字符 ^ $
如果只想讓"the"在行首的行列出怎么做:
[~]$ grep -n '^the' regular_express.txt
如果想要開頭是小寫字符的那一行就列出怎么做:
[~]$ grep -n '^[a-z]' regular_express.txt
[~]$ grep -n '^[[:lower:]]' regular_express.txt
如果不想開頭是英文字母怎么做:
[~]$ grep -n '^[^a-zA-z]' regular_express.txt
[~]$ grep -n '^[^[:alpha:]]' regular_express.txt
如果想要找出行尾有小數(shù)點(diǎn)"."的那一行怎么做:
[~]$ grep -n '\.$' regular_express.txt ## 注意:這里的小數(shù)點(diǎn)需要轉(zhuǎn)義
如果想要找出"空白行"怎么做?
[~]$ grep -n '^$' regular_express.txt ## 因?yàn)橹挥行惺缀托形玻@樣就找出空白行了。
假設(shè)有一個(gè)shell script,空白行和#的那一行是批注,因此想要省略掉這些行,怎么做?
[~]$ grep -v '^$' regular_express.txt | grep -v '^#' regular_express.txt
*示例4:任意一個(gè)字符 . 與重復(fù)字符 **
在正規(guī)表示法"*"并不是通配符:
. :表示一定有一個(gè)任意字符;
- :表示重復(fù)前一個(gè)字符,0到無窮次;
如果我們想要找出"g??d"的字符怎么做:
[~]$ grep -n 'g..d' regular_express.txt ## 表示g和d之間必須存在兩個(gè)字符
""表示重復(fù)0個(gè)或多個(gè)前面的字符,因此"o"表示:擁有空字符或一個(gè)o以上的字符。
[~]$ grep -n 'o*' regular_express.txt ## 因?yàn)樵试S空字符,所以將會(huì)把所有的數(shù)據(jù)都打印出來
如果是"oo"呢?第1個(gè)"o"必須存在,第2個(gè)"o"是可有可無的多個(gè)"o",所以,凡是有"o,oo,oooo"等等,都被列出來;同理,當(dāng)需要至少2個(gè)o以上的字符串時(shí),就需要"ooo"。
[~]$ grep -n 'ooo*' regular_express.txt
如果想找出g開頭與g結(jié)尾的字符串,當(dāng)中的字符可有可無怎么做?是"gg"嗎?"g"表示空字符或一個(gè)以上的g,在加上后面的g,所以搜索的內(nèi)容就是g,gg,ggg,gggg。只要該行中擁有一個(gè)以上的g就符合了。
那如何找出g.....g的行?可以使用任意一個(gè)字符"."。
[~]$ grep -n 'g.*g' regular_express.txt ## ". *"表示0個(gè)或多個(gè)任意字符
如果想要找出任意數(shù)字的行怎么做:
[~]$ grep -n '[0-9][0-9]*' regular_express.txt ## 雖然[0-9]就可以達(dá)到效果,但是希望可以理解這個(gè)表達(dá)式的意義。
示例5:限定連續(xù)正規(guī)表示法的字符范圍:{}
如果想找到2個(gè)o的字符串怎么做:
[~]$ grep -n 'o\{2\}' regular_express.txt ## 因?yàn)閧 }在shell是有特殊意義的,所以需要轉(zhuǎn)義。
如果想找到g后面接2到5個(gè)o的字符串,再接一個(gè)g的字符串怎么做:
[~]$ grep -n 'go\{2,5\}g' regular_express.txt
如果想要2個(gè)o以上的字符串"gooo...g"呢?除了gooo*g也可以是:
[~]$ grep -n 'go\{2,\}g' regular_express.txt
2.5 基礎(chǔ)正規(guī)表達(dá)式字符匯整
^word :搜索的字符串(word)在行首;
word$ : 搜索的字符串(word)在行尾;
. :表示"一定有一個(gè)任意字符"的字符;
\ :轉(zhuǎn)義;
* :重復(fù)0個(gè)到無窮個(gè)前一個(gè)RE字符;
[list] :表示字符集合的RE字符,里面列出想搜索的;
[n1-n2]:表示字符集合的RE字符,里面列出想要獲取的范圍;
[^list] :表示字符集合的RE字符,里面列出不想要的字符串或范圍;
\{n,m\} :表示n到m個(gè)的"前一個(gè)RE字符";
2.6 sed工具
sed本身是一個(gè)管道命令,可以分析stdin了。
功能簡(jiǎn)介:
[~]$ sed [-nefr] [動(dòng)作]
選項(xiàng)與參數(shù):
-n :使用安靜(silent)模式,一般sed中,所有stdin的數(shù)據(jù)都會(huì)被顯示。如果使用-n后,只有經(jīng)過sed特殊處理的那一行或動(dòng)作才會(huì)被顯示出來;
-e :直接在指令列模式上進(jìn)行sed動(dòng)作編輯;
-f :直接將sed的動(dòng)作寫在一個(gè)文件內(nèi), -f filename 執(zhí)行filename的sed動(dòng)作;
-i :直接修改讀取的文件內(nèi)容,而不是由屏幕輸出;
動(dòng)作說明:[n1[,n2]]fuction
n1,n2 :可以不存在,一般表示"選擇進(jìn)行動(dòng)作的行數(shù)"。例如:需要在10到20行之間進(jìn)行的動(dòng)作表示為 10,20[fuction];
fuction 列表:
a :新增,后面接字符串,這些字符串會(huì)在新的一行出現(xiàn)(當(dāng)前的上一行);
c :替換,后面接字符串,這些字符串可以替換n1到n2之間的行;
d :刪除;
i :插入,后面接字符串,這些字符串會(huì)在新的一行出現(xiàn)(當(dāng)前上一行);
p :打印,將某個(gè)選擇的數(shù)據(jù)打印出來,通常與 -n 一起使用;
s :替換,可以直接進(jìn)行替換。通常這個(gè)s的動(dòng)作搭配正規(guī)表示法。
以行為單位的新增/刪除
示例1 :將/etc/passwd的內(nèi)容列出并打印行號(hào),同時(shí)將2-5行刪除
[~]$ nl /etc/passwd | sed '2,5d' ## 刪除第2行'2d';刪除2到最后一行'3,$d'
示例2 :接上示例,在第二行后加上"drink tea?"
[~]$ nl /etc/passwd |sed '2a drink tea?'
以行為單位的替換與顯示
示例3 :將2-5行的內(nèi)容替換為"No 2-5 number"
[~]$ nl /etc/passwd |sed '2,5c No 2-5 number'
示例4 :將/etc/passwd文件內(nèi)的第5-8行列出來
[~]$ nl /etc/passwd | sed -n '5,8p'
數(shù)據(jù)的搜索并取代功能
[~]$ sed 's/要被取代的字符串/新的字符串/g'
示例1:查詢IP
[~]$ ifconfig en4
示例2:接上一示例,根據(jù)'inet '獲取結(jié)果
[~]$ ifconfig en4 | grep 'inet '
示例3:接上一示例,將IP前面的部分刪除
[~]$ ifconfig en4 | grep 'inet ' | sed 's/^.*inet //g'
示例4:接上一示例,將IP后面的部分刪除
[~]$ ifconfig en4 | grep 'inet ' | sed 's/^.*inet //g' | sed 's/ *netmask.*$//g'
示例5: /etc/man_db.conf中帶有"MAN"的獲取出來,刪除批注行和空白行;
[~]$ cat /etc/man.conf |grep 'MAN' | sed 's/#.*//g' |sed '/^$/d' ## /^$/ 表示空白行
直接修改文件內(nèi)容(慎用)
示例6:利用sed將regular_express.txt 內(nèi)的每一行結(jié)尾為"."換成"!"
[~]$ sed -i 's/\.$/\!/g' regular_express.txt
示例7:利用sed直接在regular_express.txt最后一行加入"#This is a test"
[~]$ sed -i '$a # This is a test' regular_express.txt
正規(guī)表示法的擴(kuò)展
例如上面有一個(gè)例子是在regular_express.txt中去除空白行與行首為#的行,使用的是
"grep -v '^$' regular_express.txt | grep -v '^#' "
可以簡(jiǎn)化為:
"egrep -v '$|#' regular_express.txt"
正規(guī)表示法擴(kuò)展有哪些特殊符號(hào)?
+ :表示重復(fù)1個(gè)或1個(gè)以上的前一個(gè)RE字符; ## egrep -n 'go+d' regular_express.txt
? :表示0個(gè)或1個(gè)的前一個(gè)RE字符; ## egrep -n 'go?d' regular_express.txt
() :找出群組的字符串; ## egrep -n 'g(la|oo)d' regular_express.txt
()+:找出群組的字符串; ## echo AxyzxyzC | egrep 'A(xyz)+C' 意思是找出開頭是A,結(jié)尾是C,包含1個(gè)以上xyz的字符串;
3.文件的格式化與相關(guān)處理
3.1 格式化打印:printf
功能簡(jiǎn)介:
[~]$ printf '打印格式' 實(shí)際內(nèi)容
選項(xiàng)與參數(shù):
\a :警告聲音輸出;
\b :刪除鍵;
\f :清除屏幕;
\n :輸出新的一行;
\r :即enter鍵;
\t :水平的[tab]鍵;
\v :垂直的[tab]鍵;
\xNN :NN為2位數(shù)的數(shù)字,可以轉(zhuǎn)換數(shù)字成為字符;
C語言中,常見的變數(shù)格式:
%ns :n是數(shù)字,s代表string,即n個(gè)字符串;
%ni :n是數(shù)字,i代表integer,即n個(gè)整數(shù)數(shù)字;
%N.nf:n和N都為數(shù)字,f代表floating。表示加上小數(shù)點(diǎn)一個(gè)N個(gè)字符,小數(shù)點(diǎn)后面保留n位;
3.2 awk:數(shù)據(jù)處理工具
awk比較傾向于一行當(dāng)中分成數(shù)字字段來處理,默認(rèn)的字段分隔符為"空格鍵"或"tab鍵"。
功能簡(jiǎn)介:
[~]$ awk '條件類型1{動(dòng)作1}條件類型2{動(dòng)作2}...' filename
示例1:使用last取出前5行,只取出賬號(hào)與IP。
[~]$ last -n 5 | awk '{print $1 "\t" $3}' ## $1,$2,$3...表示每一行的每個(gè)字段的變量名稱。$0則代表一整行的意思。
接下來了解以下awk有哪些變量:
NF :每一行($0)擁有的字段總數(shù);
NR :目前awk處理的是第幾行的數(shù)據(jù);
FS :分割字符,默認(rèn)是空格鍵;
舉例來說:/etc/passwd中以冒號(hào)作為分隔符,該文件第1個(gè)字段是賬號(hào),第3個(gè)字段是UID。那想要查閱第3欄小于10的數(shù)據(jù)怎么做:
[~]$ cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t" $3}'
## 這個(gè)BEGIN又是什么?它可以預(yù)先設(shè)定awk的變量!如果我們不加這個(gè)關(guān)鍵詞,那么當(dāng)我們讀入第一行數(shù)據(jù)時(shí)候,它默認(rèn)還是以空格鍵為分隔的!
假設(shè)有一下文本:
[~]$ cat text.txt
Name 1st 2nd 3th
tony 20 20 30
tom 10 30 35
jerry 5 45 45
如果想要計(jì)算每個(gè)人的總額怎么算?還需要格式化輸出。
[~]$ cat test.txt | awk 'NR==1{printf "%10s %5s %5s %5s %5s",$1,$2,$3,$4,"Total\n"} NR>=2{printf "%10s %5d %5d %5d %5.2f\n",$1,$2,$3,$4,$1+$2+$3+$4}'
另外,awk的動(dòng)作{}內(nèi)也支持if條件,上面的指令可以修改為以下這樣:
[~]$ cat test.txt | awk '{if (NR==1) printf "%10s %5s %5s %5s %5s",$1,$2,$3,$4,"Total\n"} {printf "%10s %5d %5d %5d %5.2f\n",$1,$2,$3,$4,$1+$2+$3+$4}'
3.3 文件比對(duì)工具
diff
diff用來比對(duì)兩個(gè)文件之間的差異,以行為單位來比對(duì)的。
示例:將/etc/passwd備份為passwd.old后,把第4行刪除,第6行替換為no line,再另存為passwd.new,怎么做呢?
[~]$ cat passwd.old | sed -e '4d' -e '6c no line' > passwd.new
接下來了解一下diff的使用:
[~]$ diff [-bBi] from-file to-file
選項(xiàng)與參數(shù):
from-file :原始對(duì)比文件檔名;
to-file :目標(biāo)對(duì)比文件檔名;
提示:from-file/to-file可以使用"-"替換,表示"stdin";
-b :忽略一行中僅有多個(gè)空白的差異(例如"a b"和"a b"忽略差異);
-B :忽略空白行的差異;
-i :忽略大小寫的不同;
cmp
cmp在比對(duì)文件的時(shí)候,主要是利用字節(jié)單位去比對(duì)的。
[~]$ cmp [-l] file1 file2
選項(xiàng)與參數(shù):
-l :將所有的不同點(diǎn)的字節(jié)出都列出來。預(yù)設(shè)僅會(huì)輸出第一個(gè)發(fā)現(xiàn)的不同點(diǎn)。
patch
將舊的文件升級(jí)成新的文件,經(jīng)常與diff搭配使用。
示例1:制作passwd.old與passwd.new補(bǔ)丁文件
[~]$ diff -Naur passwd.old passwd.new > passwd.patch
[~]$ cat passwd.patch ##可以看到passwd.old到passwd.new做了哪些修改,一般使用diff制作的補(bǔ)丁文件通常使用擴(kuò)展名.patch。
功能簡(jiǎn)介:
[~]$ patch -pN < patch_file ##更新;
[~]$ patch -R -pN < patch_file ##還原;
選項(xiàng)與參數(shù):
-p :加"取消幾層目錄",N為數(shù)字;
-R :表示將新的文件還原成原來舊的文件;
示例2:將剛剛制作出來的path file用來更新舊版數(shù)據(jù)
[~]$ patch -p0 < passed.patch
[~]$ ls -l passwd*
示例3:恢復(fù)舊的文件內(nèi)容
[~]$ patch -R -p0 < passwd.patch
[~]$ ls -l passwd*
因?yàn)樾屡f版的數(shù)據(jù)是在同一個(gè)目錄下的,所以是"-p0"。