文字處理三劍客
1、簡介
awk、grep、sed是linux操作文字的三大利器,合稱文字三劍客。三者的功能都是處理文字,但側重點各不相同,其中屬awk功能最強大,但也最複雜。grep更適合單純地查詢或匹配文字;sed更適合編輯匹配到的文字,awk更適合格式化文字,對文字進行較複雜格式處理。
2、grep
2.1、什麼是grep和egrep
Linux系統中grep命令是一種強大的文字搜尋工具,它能使用正則表示式搜尋文字,並將匹配的行打印出來(匹配到的標紅)。grep全稱是Global Regular Expression Print,表示全域性正則表示式版本,它的使用許可權是所有使用者。
grep的工作方式是這樣的,它在一個或多個檔案中搜索字串模板。如果模板包括空格,則必須被引用,模板後的所有字串被看做是檔名。搜尋的結果被送到標準輸出,不影響原檔案內容
grep可用於shell指令碼,因為grep通過一個返回狀態值來說明搜尋的狀態,如果模板搜尋成功,則返回0;如果搜尋不成功,則返回1;如果搜尋的檔案不存在,則返回2。可利用這些返回值進行一些自動化的文字處理工作。
egrep等同於grep -E:擴充套件的正則表示式(除了\<,\>,\b之外,使用其他正則都可以去掉\)
2.2、使用grep
2.2.1、命令格式
grep [option] pattern file
2.2.2、命令功能
用於過濾/搜尋特定字元。可配合正則表示式來進行使用,使用上十分靈活。
2.2.3、命令引數
常用引數已加粗。
- -A<顯示行數>:除了顯示符合樣式的那一行之外,並顯示該行之後的內容。
- -B<顯示行數>:除了顯示符合樣式的那一行之外,並顯示該行之前的內容。
- -C<顯示行數>:除了顯示符合樣式的那一行之外,並顯示該行之前後的內容。
- -c:統計匹配的行數
- -e:實現多個選項間的邏輯or關係
- -E:擴充套件的正則表示式
- -f file:從file獲取pattern匹配
- -F:相當於fgrep
- -i --ignore-case:忽略字元大小寫的差別
- -n:顯示匹配的行號
- -o:僅顯示匹配到的字串
- -q:靜默模式,不輸出任何資訊
- -s:不顯示錯誤資訊
- -v:顯示不被pattern匹配到的行,相當於[^]反向匹配
- -w:匹配整個單詞
2.2.4、實戰演示
# [root@docker test]# cat grep.txt aaa [root@docker test]# cat test aaa bbbbb AAAaaa BBBBASDABBDA #以grep.txt中每一行為關鍵字,查詢test檔案中匹配的行 [root@docker test]# grep -f grep.txt test aaa AAAaaa
3、正則表示式
3.1 分類
POSIX規範將正則表示式分為了兩種
- 基本正則表示式(BRE,basic regular expression)
- 高階功能:擴充套件正則表示式(ERE,extended regular expression)
BRE和ERE的區別僅僅是元字元的不同
- BRE只承認的元字元有^$.[]*,其他字元識別為普通字元;
- ERE則添加了(){}?+|等
- 只用在用反斜槓“\”進行轉義的情況下,字串(){}才會在BRE被當做元字元處理,而在BRE中,任何元字元前面加上反斜槓反而會使其被當做普通字元來處理。
3.2、基本正則表示式
3.2.1、格式
字元 | 描述 |
---|---|
^ | ^word:搜尋以word開頭的內容 |
$ | word$:搜尋以word結尾的內容 |
^$ | 表示空行,不是空格 |
. | 代表且只能代表任意一個字元(不匹配空行) |
\ | 轉義字元,讓有特殊含義的字元脫掉馬甲,現出原形,如\.只表示小數點 |
* | 匹配前面的字元任意次,包括0次,貪婪模式:儘可能長的匹配 |
.* | 任意長度的任意字元,不包括0次 |
^.* | 以任意多個字串開頭,.*儘可能多,有多少算多少,貪婪性 |
[^abc] | 匹配不包含^後的任意字元a或b或c,是對[abc]的取反 |
a\{n,m\} | 重複前面a字元至少n次,至多m次(如使用egrep或sed -r可去掉斜線) |
3.2.2、演練
3.3、擴充套件正則表示式
3.3.1、格式
特殊字元 | 描述 |
---|---|
+ | 重複前一個字元一次或多次 |
? | 重複前一個字元0次或1次(.是有且只有1個) |
| | 表示或,查詢多個字串 |
() | 分組過濾被括起來的東西表示一個整體(一個字元) |
3.3.2、演練
3.4、基本正則和擴充套件正則區別
所謂基礎正則,實際上就是得需要轉義字元配合表達的正則,而擴充套件正則就是讓命令擴充套件它的許可權讓其直接就認識正則表達符號
BRE | ERE |
---|---|
? | ? |
\+ | + |
\{\} | {} |
\(\) | () |
\ |
3.5、補充說明
3.5.1、預定義
正則表示式 | 描述 | 示例 |
---|---|---|
[:alnum:] | [a-zA-Z0-9]匹配任意一個字母或數字字元 | [[:alnum:]]+ |
[:alpha:] | 匹配任意一個字母字元(包括大小寫字母) | [[:alpha:]]{4} |
[:blank:] | 空格與製表符(橫向縱向) | [[:blank:]]* |
[:digit:] | 匹配任意一個數字字元 | [[:digit:]]? |
[:lower:] | 匹配小寫字母 | [[:lower:]]{5,} |
[:upper:] | 匹配大寫字母 | ([[:upper:]]+)? |
[:punct:] | 匹配標點符號 | [[:punct:]] |
[:space:] | 匹配一個包括換行符,回車等在內的所有空白符 | [[:space:]]+ |
[:graph:] | 匹配任何一個可以看得見的且可以列印的字元 | [[:graph:]] |
[:xdigit:] | 任何一個十六進位制數 | [[:xdigit:]]+ |
[:cntrl:] | 任何一個控制字元(ASCII字符集中的前32個字元) | [[:cntrl:]] |
[:print:] | 任何一個可以列印的字元 | [[:print:]] |
3.5.2、元字元
元字元是一種Perl風格的正則表示式,只有一部分文字處理工具支援它,並不是所有的文字處理工具都支援。
正則表示式 | 描述 | 示例 |
---|---|---|
\b | 單詞邊界 | \bcool\b匹配cool,不匹配coolant |
\B | 非單詞邊界 | cool\B匹配coolant不匹配cool |
\d | 單個數字字元 | b\db匹配b2b,不匹配bcb |
\D | 單個非數字字元 | b\Db匹配bcb不匹配b2b |
\w | 單個單詞字元(字母,數字與_) | \w匹配1或a,不匹配& |
\W | 單個非單詞字元 | \W匹配&,不匹配1或a |
\n | 換行符 | \n匹配一個新行 |
\s | 單個空白字元 | x\sx匹配xx,不匹配xx |
\S | 單個非空白字元 | x\S\x匹配xkx,不匹配xx |
\r | 回車 | \r匹配回車 |
\t | 橫向製表符 | \t匹配一個橫向製表符 |
\v | 垂直製表符 | \v匹配一個垂直製表符 |
\f | 換頁符 | \f匹配一個換頁符 |
4、sed
4.1、認識sed
sed是一種流編輯器,它一次處理一行內容。處理時,把當前處理的行儲存在臨時緩衝區中,稱為“模式空間”,接著用sed命令處理緩衝區中的內容,處理完成後,把緩衝區的內容送往螢幕。然後讀入下一行,執行下一個迴圈。如果沒有使用諸如“D”的特殊命令,那會在兩個迴圈之間清空模式空間,但不會清空保留空間。這樣不斷重複,直到檔案末尾。檔案內容並沒有改變,除非使用重定向儲存輸出或-i。
功能:主要用來自動編輯一個或多個檔案,簡化對檔案的反覆操作。
4.2、使用sed
4.2.1、命令格式
sed [選項] [command] 檔名
4.2.2、常用選項
- -n:不輸出模式空間內容到螢幕,即不自動列印,只打印匹配到的行
- -e:多點編輯,對每行處理時,可以有多個script
- -f:把script寫到文件中,在執行sed時,-f指定檔案路徑;如果有多個script,換行寫入
- -r:支援擴充套件的正則表示式
- -i:直接將處理的結果寫入檔案
- -i.bak:在將處理的結果寫入檔案之前備份一份
4.2.3、地址定界
- 不給地址:對全文進行處理
- 單地址:
- #: 指定的行
- /pattern/:被此處模式所能夠匹配到的每一行
- 地址範圍:
- #,#
- #,+#
- /pat1/,/pat2/
- #,/pat1/
- ~:步進
- sed -n '1~2p' 只打印奇數行 (1~2 從第1行,一次加2行)
- sed -n '2~2p' 只打印偶數行
4.2.4、編輯命令
- d:刪除模式空間匹配的行,並立即啟用下一輪迴圈
- p:列印當前模式空間內容,追加到預設輸出之後
- a:在指定行後面追加文字,支援使用\n實現多行追加
- i:在行前面插入文字,支援使用\n實現多行追加
- c:替換行為單行或多行文字,支援使用\n實現多行追加
- w:儲存模式匹配的行至指定檔案
- r:讀取指定檔案的文字至模式空間中匹配到的行後
- =:為模式空間中的行列印行號
- !:模式空間中匹配行取反處理
- s///:查詢替換,支援使用其它分隔符,如:s@@@,s###;
- 加g表示行內全域性替換;
- 在替換時,可以加一下命令,實現大小寫轉換
- \l:把下個字元轉換成小寫。
- \L:把replacement字母轉換成小寫,直到\U或\E出現。
- \u:把下個字元轉換成大寫。
- \U:把replacement字母轉換成大寫,直到\L或\E出現。
- \E:停止以\L或\U開始的大小寫轉換
4.3、演練
4.3.1、常用選項options
[root@aliyun shell]# cat demo
aaa
bbbb
AABBCCDD
[root@aliyun shell]# sed "/aaa/p" demo #匹配到的行會列印一遍,不匹配的行也會列印
aaa
aaa
bbbb
AABBCCDD
[root@aliyun shell]# sed -n "/aaa/p" demo #僅列印匹配的行,-n,不顯示沒匹配的行
aaa
[root@aliyun shell]# sed -e "s/a/A/" -e "s/b/B" demo
sed:-e 表示式 #2,字元 5:未終止的“s”命令
[root@aliyun shell]# sed -e "s/a/A/" -e "s/b/B/" demo #-e多點編輯
Aaa
Bbbb
AABBCCDD
[root@aliyun shell]# cat sedscript.sed
s/a/A/g
[root@aliyun shell]# sed -f sedscript.sed demo #-f 使用檔案處理
AAA
bbbb
AABBCCDD
[root@aliyun shell]# sed -i.bak "s/a/A/g" demo #-i.bak直接對文字進行處理,同時將原文字備份為.bak檔案
[root@aliyun shell]# cat demo
AAA
bbbb
AABBCCDD
[root@aliyun shell]# cat demo.bak
aaa
bbbb
AABBCCDD
4.3.2、地址界定
[root@aliyun shell]# cat demo
aaa
bbbb
AABBCCDD
[root@aliyun shell]# sed -n "p" demo #不指定行,列印全部內容
aaa
bbbb
AABBCCDD
[root@aliyun shell]# sed "2s/b/B/g" demo #替換第2行的b為B
aaa
BBBB
AABBCCDD
[root@aliyun shell]# sed -n "/aaa/p" demo
aaa
[root@aliyun shell]# sed -n "1,2p" demo #列印1-2行
aaa
bbbb
[root@aliyun shell]# sed -n "/aaa/,/DD/p" demo #列印aaa-DD行
aaa
bbbb
AABBCCDD
[root@aliyun shell]# sed -n "2,/DD/p" demo #列印2-DD行
bbbb
AABBCCDD
[root@aliyun shell]# sed "1~2s/[aA]/E/g" demo #將奇數行的a或A替換為E
EEE
bbbb
EEBBCCDD
4.3.3、編輯命令command
[root@aliyun shell]# cat demo
aaa
bbbb
AABBCCDD
[root@aliyun shell]# sed "2d" demo #刪除第2行
aaa
AABBCCDD
[root@aliyun shell]# sed -n "2p" demo #列印第二行
bbbb
[root@aliyun shell]# sed "2a123" demo #將123新增到第二行後面
aaa
bbbb
123
AABBCCDD
[root@aliyun shell]# sed "1i123" demo #將123新增到第一行前面
123
aaa
bbbb
AABBCCDD
[root@aliyun shell]# sed "3c123\n456" demo #將123\n456替換第三行
aaa
bbbb
123
456
[root@aliyun shell]# sed -n "3w/home/shell/demo3" demo #將第三行寫到/home/shell/demo3檔案中
[root@aliyun shell]# cat demo3
AABBCCDD
[root@aliyun shell]# sed "1r/home/shell/demo3" demo #將/home/shell/demo3檔案中內容讀取到第一行後面
aaa
AABBCCDD
bbbb
AABBCCDD
[root@aliyun shell]# sed -n "=" demo #列印行號
1
2
3
[root@aliyun shell]# sed "s@[a-z]@\u&@g" demo #將所有小寫字母轉換為大寫
AAA
BBBB
AABBCCDD
[root@aliyun shell]# sed -n '2!p' demo #除第二行內容外,全部列印
aaa
AABBCCDD
4.4、sed高階編輯命令
4.4.1、格式
- h:將模式空間中的內容覆蓋至保持空間中
- H:將模式空間中的內容追加至保持空間中
- g:從保持空間取出資料覆蓋至模式空間
- G:從保持空間取出資料追加至模式空間
- x:將模式空間中的內容與保持空間中的內容進行互換
- n:讀取匹配到的行的下一行覆蓋至模式空間
- N:讀取匹配到的行的下一行追加至模式空間
- d:刪除模式空間中的行
- D:刪除當前模式空間開端到\n的內容(不再傳至標準輸出),放棄之後的命令,但是對剩餘模式空間重新執行sed
4.4.2、案例+示意圖
#倒敘輸出檔案內容
[root@aliyun shell]# cat num.txt
1
2
3
[root@aliyun shell]# sed '1!G;h;$!d' num.txt
3
2
1
示意圖:
4.4.3、總結
保持空間是模式空間一個臨時存放資料的緩衝區,協助模式空間進行資料處理
4.4.4、演練
#顯示偶數行
[root@aliyun shell]# seq 9 | sed -n "n;p"
2
4
6
8
#倒敘顯示
[root@aliyun shell]# seq 9 | sed '1!G;h;$!d'
9
8
7
6
5
4
3
2
1
#顯示奇數行
[root@aliyun shell]# seq 9 | sed "H;n;d"
1
3
5
7
9
#列印最後一行
[root@aliyun shell]# seq 9 | sed "N;D"
9
#每行之間加空行
[root@aliyun shell]# seq 9 | sed "G"
1
2
3
4
5
6
7
8
9
#將每行內容替換成空行
[root@aliyun shell]# seq 9 | sed "g"
#確保每一行下面都有一個空行
[root@aliyun shell]# seq 9 | sed '/^$/d;G'
1
2
3
4
5
6
7
8
9
5、awk
5.1、簡介
awk是一種程式語言,用於在linux/unix下對文字和資料進行處理。資料可以來自於標準輸入、一個或多個檔案、或其他命令的輸出。它支援使用者自定義函式和動態正則表示式等功能,是linux/unix下的一個強大的程式設計工具。它在命令列中使用,但更多是作為指令碼使用。awk有很多內建的功能,比如陣列、函式等。
5.2、使用awk
5.2.1、語法
[root@localhost ~]# awk [選項] '指令碼命令' 檔名
5.2.2、常用命令選項
- -F fs:指定以fs作為輸入行的分隔符,awk命令預設分隔符為空格或製表符
- -v var=value:在執行處理過程之前,設定一個變數var,並給其設定初始值
- -f scriptfile:從指令碼檔案中讀取awk命令,以取代直接在命令列中輸入指令
awk的強大之處
awk的強大之處在於指令碼命令,它由兩部分組成,分別為匹配規則和執行命令,如下所示:
'匹配規則{執行命令}'
這裡的匹配規則,用來指定指令碼命令中可以作用到文字內容中的具體行,可以使用字串(比如/demo/,表示檢視含有demo字串的行)或正則表示式指定。
注:整個指令碼命令是用單引號括起來,而其中的執行命令部分需要用大括號括起來
5.3、awk變數
5.3.1、內建變數
變數 | 描述 |
---|---|
FS | 輸入字元分隔符,預設為空白字元 |
OFS | 輸出欄位分隔符,預設為空白字元 |
RS | 輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效 |
ORS | 輸出記錄分隔符,輸出時用指定符號代替換行符 |
NF | 字元數量,共有多少個欄位,$NF引用最後一列,$(NF-1)引用倒數第二列 |
NR | 行號,後可跟多個檔案,第二個檔案行號則繼續從第一個檔案最後行號開始 |
FNR | 各檔案分別計數,行號;後跟一個檔案和NR一樣,跟多個檔案,第二個檔案行號從1開始 |
FILENAME | 當前檔名 |
ARGC | 命令列引數的個數 |
ARGV | 陣列,儲存的是命令列所給定的各引數,檢視引數 |
示例:
[root@aliyun shell]# cat awkdemo
hello:world
linux:redhat:lalala:hahaha
along:love:you
[root@aliyun shell]# awk -v FS=":" '{print $1,$2}' awkdemo #FS指定輸入分隔符
hello world
linux redhat
along love
[root@aliyun shell]# awk -v FS=":" -v OFS="---" '{print $1,$2}' awkdemo #OFS指定輸出分隔符
hello---world
linux---redhat
along---love
[root@aliyun shell]# awk -v RS=":" '{print $1,$2}' awkdemo
hello
world linux
redhat
lalala
hahaha along
love
you
[root@aliyun shell]# awk -v FS=":" -v ORS="---" '{print $1,$2}' awkdemo
hello world---linux redhat---along love---
[root@aliyun shell]# awk -F: '{print NF}' awkdemo
2
4
3
[root@aliyun shell]# awk -F: '{print $(NF-1)}' awkdemo
hello
lalala
love
[root@aliyun shell]# awk END'{print NR}' awkdemo
3
5.3.2、自定義變數
1、先定義變數,後執行動作
[root@aliyun shell]# cat awkdemo
hello:world
linux:redhat:lalala:hahaha
along:love:you
[root@aliyun shell]# awk -v name="along" -F: '{print name":"$0}' awkdemo
along:hello:world
along:linux:redhat:lalala:hahaha
along:along:love:you
2、先執行動作,後定義變數
[root@aliyun shell]# awk -F: '{print name":"$0;name="along"}' awkdemo
:hello:world
along:linux:redhat:lalala:hahaha
along:along:love:you
3、呼叫指令碼進行定義
[root@aliyun shell]# cat awk.txt
{name="along";print name,$1}
[root@aliyun shell]# awk -F: -f awk.txt awkdemo
along hello
along linux
along along
[root@aliyun shell]#
6、grep、sed、awk對比
- grep主要用於搜尋某些字串;sed和awk用於處理文字。
- grep基本是以行為單位處理文字的
- sed是一個非互動性文字流編輯器,它編輯檔案或標準輸入匯出的文字拷貝。sed編輯器按照一次處理一行的方式來處理檔案(或輸入)並將輸出送到螢幕上。sed把當前正在處理的行儲存在一個臨時快取裡,這個快取叫做模式空間;一旦sed完成了對模式空間裡的行的處理,就把模式空間的行送到螢幕上(除非該命令要刪除該行或禁止列印);處理完該行之後,從模式空間中刪除它,然後把下一行讀入模式空間,進行處理並顯示。當輸入檔案的最後一行處理完後,sed終止。通過將每一行存到一個臨時快取裡並編輯該行,初始檔案不會被修改或被破壞。
- awk和sed一樣,也是逐行讀取,是以欄位為單位來處理文字