前言
經(jīng)常會用到相關的文本處理命令來查詢信息,有些語法太久沒用就忘了經(jīng)常需要去查資料,于是就想整理一篇文章出來方便自己查看,也希望對各位讀者有所幫助。
一、cut命令
cut命令是一個相對比較簡單的命令,主要用來做文本的切割,和之前介紹過的split命令不同,cut命令是根據(jù)文本內(nèi)容來做切割的,而不是根據(jù)文件大小來進行切割的。
| 參數(shù) | 作用 |
|---|---|
| -f | 指定要哪一列的數(shù)據(jù),多列數(shù)據(jù)則用逗號隔開,相連的列可以用中橫線表示比如3-5
|
| -d | 指定分隔符,默認情況下cut命令用制表符來進行分隔 |
| -n | 顯示行號 |
我們給一個測試文件,一共有三列數(shù)據(jù),我們希望把第1列和第3列的數(shù)據(jù)提取出來放到一個新的文件里面
Jack Boy 19
Marry Girl 15
John Boy 45
Amy Girl 30
通過觀察我們可以發(fā)現(xiàn)文件是以空格來進行文本分隔的,我們可以通過cut -d " " -f 1,3 cut_test > cut_result.log這個命令來實現(xiàn)
最后輸出結果如下

注意事項:cut雖然簡單易用,但除了比較簡單的場景外我們用的比較少,原因就是cut只支持單個字符作為分隔符,對于多字符或者不規(guī)則字符分隔的列就很不好用了。比如ps -ef的結果集
二、awk命令
awk是比cut命令更加強大的文本處理工具,不僅體現(xiàn)在文本分割更加靈活,awk還有著強大的文本處理能力。
awk [選項] ‘[BEGIN] 模式或條件 {操作} [END]’ 文件1 文件2...
(一)常用選項
| 選項 | 作用 |
|---|---|
| -F | 指定分隔符,默認為空白字符 |
| -v var=value | 再程序開始前設置變量 |
(二)內(nèi)置變量
| 變量名 | 作用 |
|---|---|
| $0 | 當前處理行整行的內(nèi)容 |
| $n | 當前處理行的第n列 |
| NR | 當前處理行的行號 |
| NF | 當前處理行的字段數(shù) |
| FS | 輸入字段分隔符(默認為空白字符) |
| OFS | 輸出字段分隔符(默認為空白字符) |
| FILENAME | 當前被處理的文件名 |
| RS | 輸出記錄分隔符(默認為換行符) |
(三)工作原理
- BEGIN 語句塊:在處理任何輸入行之前執(zhí)行,主要用于初始化操作
- 處理輸入行:對于每一行輸入,awk 會檢查是否匹配指定的模式或條件,如果匹配,則執(zhí)行相應的操作。
- END 語句塊:在處理完所有輸入行之后執(zhí)行,常用于匯總或輸出最終結果。
(四)案例演示
1. 獲取現(xiàn)在所有java進程對應的啟動用戶和進程號
cut命令做不到的切分到這里就順利實現(xiàn)了!
ps -ef | grep java | awk '{print $1 " " $2}'
2、指定分隔符進行切分
有如下文本,文本內(nèi)容通過aba進行分隔的,我們現(xiàn)在按照aba作為分隔符進行分隔,取第1,2列
JackabaBoyaba19
MarryabaGirlaba15
JohnabaBoyaba45
AmyabaGirlaba30
對應的腳本內(nèi)容如下:
awk -F 'aba' '{print $1 " " $2}' awk_test

3、打印文本指定行數(shù)
我們希望分別打印文件中第1,3行和第2-4行到新的文件中,這里節(jié)省一下空間我們就還是沿用cut中的案例
- 打印文本中的第1行和第3行
awk 'NR==1 || NR==3 {print $0}' awk_test

- 打印文本中的第2-4行
下面2種語法都可以實現(xiàn)
awk 'NR==1, NR==3 {print $0}' awk_test
awk '(NR>=1)&&(NR<=3) {print $0}' awk_test
4、在輸出結果中的前面加入行號打印
這里其實可以結合cut、cat命令來輔助我們做新的行號,不過為了方便演示awk的語法,我們就還是用awk來實現(xiàn)
awk '{print NR " " $0}' awk_test

5、加入標題和結尾
我們可以使用BEGIN和END來在所有文本處理前后加一下打印語句,比較多的話是加一下標題,然后在結束的地方加一下結束語或者是做一下統(tǒng)計。我們這里就簡單寫一個用例吧,在處理前后打印一下開始和結束的關鍵字
awk 'BEGIN {print "===START EXECUTE==="} {print $0} END {print "===END==="}' awk_test

6、根據(jù)關鍵詞or正則進行過濾
awk在文本過濾上面也是一把好手,我們可以使用/regex/{print}的方式來實現(xiàn)文本過濾,比如說我們希望把性別為女的數(shù)據(jù)給篩選出來,可以有幾種方式來實現(xiàn)
- 直接通過關鍵字進行匹配
awk '/Girl/{print $0}' awk_test
- 通過條件判斷來實現(xiàn)
awk '$2=="Girl" {print}' awk_test
7、利用BEGIN和END來做統(tǒng)計
我們知道BEGIN和END可以分別在文本處理前后做一些事情,那么我們可以利用這個特點來做一下數(shù)據(jù)的統(tǒng)計
比如說下面的文件有商品名和價格
IPhone 3000
T-Shirt 50
Bag 20
Coke 15
我們希望統(tǒng)計出文件的總行數(shù)和所有商品的價格,可以借助BEGIN來設置變量,中間過程來計算變量,END展示結果值
awk 'BEGIN {tP=0;tR=0} {print $0;tR++;tP+=$2} END {print "total Price is " tP " totalRowNum is " tR}' awk_test2

(五)進階用法
1. 利用akw命令實現(xiàn)分組
awk的功能十分強大,我們甚至可以結合數(shù)組來進行數(shù)據(jù)的分組統(tǒng)計,我們可以看下面這個文件
新華字典 30
我與地壇 15
母豬的產(chǎn)后處理 10
我與地壇 15
新華字典 30
新華字典 30
我們希望統(tǒng)計文件中每種書籍出現(xiàn)的次數(shù),格式為書名 出現(xiàn)次數(shù),并且按出現(xiàn)的次數(shù)從高到低進行展示??梢允褂孟旅娴拿顏韺崿F(xiàn)
awk '{count[$1]++;} END {for(i in count) {print i " " count[i]}}' awk_test3 | sort -rn -k 2
我們簡單解釋一下這條命令吧
-
count[$1]++創(chuàng)建一個關聯(lián)數(shù)組 count,以每行的第1個字段的值為鍵,并將該鍵的值增加 1。如果鍵不存在,它會自動創(chuàng)建并初始化為 0,然后執(zhí)行增加操作。 -
END {for(i in count) {print i count[i]}}
for(i in count)遍歷 count 數(shù)組中的所有鍵。print i " " count[i]:打印每個鍵及其對應的計數(shù),為了展示和方便計算,我們這里順便加了一個空格 -
sort -rn -k 2這里是用sort命令取第二列作為排序列,-r進行倒序排序,-n指定按數(shù)字大小進行排序

這里有讀者可能會困惑,數(shù)組的索引值一般不是數(shù)字嗎?這里怎么保證分組的字段名剛好是數(shù)字呢?這個困惑我也有過,后面查詢資料后發(fā)現(xiàn)在awk中數(shù)組的鍵(key)可以是數(shù)字、字符串或者是表達式的結果,不一定非得是數(shù)字。實際上,awk 數(shù)組更像是哈希表(hash table),而不是傳統(tǒng)意義上的數(shù)組,因為它們不是基于索引的,而是基于鍵值對的。
三、sed命令
待補充...
四、grep命令
待補充...
小結
總體來說,cut適合簡單場景的文本切割,復雜的文本不建議使用。grep更適合查日志、在文本中查關鍵字的時候使用。對于提取數(shù)據(jù)或者批量編輯數(shù)據(jù),sed和awk則更好用,當然學習成本也更高一些,個人感覺sed更適合編輯匹配到的文本,awk可以配合來做文本切割、文本處理、篩選、統(tǒng)計等這類格式化的操作。