因?yàn)楣ぷ髟蛑巢希?jīng)常經(jīng)統(tǒng)計(jì)一些文本內(nèi)容轿衔,要去除重復(fù),之前都是cat xx | sort | uniq 類的命令睦疫。
自從開始關(guān)注使用VIM之后呀枢,發(fā)現(xiàn)VIM真的很強(qiáng)大,直接有去重功能笼痛,怪不得這么多Linuxer都喜歡它裙秋。
我這里只說它的去重功能首先講點(diǎn)基礎(chǔ),
awk流程是逐行處理的缨伊,默認(rèn)從文件的第一行一直處理到文件最后一行摘刑,
還要知道awk的基本命令格式是'pattern{action}'先匹配各種各樣的樣式,然后大括號(hào)里處理如何打印輸出刻坊,
默認(rèn)的只要匹配了pattern就{print $0}枷恕,如果pattern未命中其判斷值為假(0)那么就不會(huì)再去處理{action}了
pattern命中則為判斷值為真(非0)就去處理{action}。
以下操作都是在vim命令模式下的操作
復(fù)制內(nèi)容到剪貼板
代碼:
: sort //可以直接排序谭胚,這個(gè)太好用了
:g/^\(.*\)$\n\1$/d ? ?//去除重復(fù)行
:g/\%(^\1$\n\)\@<=\(.*\)$/d //功能同上徐块,也是去除重復(fù)行
:g/\%(^\1\>.*$\n\)\@<=\(\k\+\).*$/d//功能同上,也是去除重復(fù)行
其實(shí)都是一些正則灾而,但是本人正則不太好胡控,也真的解釋不清,希望有大牛能詳細(xì)的解釋下旁趟,每個(gè)正則是神馬意思昼激!
因?yàn)楣ぷ髟颍?jīng)常經(jīng)統(tǒng)計(jì)一些文本內(nèi)容锡搜,要去除重復(fù)橙困,之前都是cat xx | sort | uniq 類的命令,自從開始關(guān)注使用VIM之后耕餐,發(fā)現(xiàn)VIM真的很強(qiáng)大凡傅,直接有去重功能,怪不得這么多Linuxer都喜歡它肠缔。我這里只說它的去重功能
以下操作都是在命令模式下的操作
復(fù)制內(nèi)容到剪貼板
代碼:
: sort //可以直接排序夏跷,這個(gè)太好用了
:g/^\(.*\)$\n\1$/d ? ?//去除重復(fù)行
:g/\%(^\1$\n\)\@<=\(.*\)$/d //功能同上,也是去除重復(fù)行
:g/\%(^\1\>.*$\n\)\@<=\(\k\+\).*$/d//功能同上桩砰,也是去除重復(fù)行
其實(shí)都是一些正則拓春,但是本人正則不太好释簿,也真的解釋不清亚隅,希望有大牛能詳細(xì)的解釋下,每個(gè)正則是神馬意思庶溶!
-------------------------------------------------------------------------------------
awk '!a[$0]++'
而如果使用sort加uniq進(jìn)行排序的話煮纵,這個(gè)文檔是看不出有什么不妥懂鸵。
不過我要處理的是用戶名與密碼一行行對(duì)應(yīng)好的,如果使用sort + uniq處理的話行疏,用戶名都排到一塊了匆光,密碼也又都跑到一塊了。
這樣就分不出來那個(gè)是那個(gè)了酿联。
而使用的腳本很簡單:
awk '!x[$0]++' filename
注:此處的x只是一個(gè)數(shù)據(jù)參數(shù)的名字而已终息,隨你用a、b贞让、c周崭、d都行。
簡要解釋一下喳张,awk 的基本執(zhí)行流程是续镇,對(duì)文件的每一行,做一個(gè)指定的邏輯判斷销部,如果邏輯判斷成立摸航,則執(zhí)行指定的命令;如果邏輯判斷不成立酱虎,則直接跳過這一行。
我們這里寫的 awk 命令是!x[$0]++擂涛,意思是:
首先創(chuàng)建一個(gè) map 叫x逢净,然后用當(dāng)前行的全文$0作為 map 的 key,到 map 中查找相應(yīng)的 value歼指,如果沒找到爹土,則整個(gè)表達(dá)式的值為真,可以執(zhí)行之后的語句踩身;
如果找到了胀茵,則表達(dá)式的值為假,跳過這一行挟阻。
由于表達(dá)式之后有++琼娘,因此如果某個(gè) key 找不到對(duì)應(yīng)的 value,該++操作會(huì)先把對(duì)應(yīng)的 value 設(shè)成 0附鸽,然后再自增成 1脱拼,這樣下次再遇到重復(fù)的行的時(shí)候,對(duì)應(yīng)的 key 就能找到一個(gè)非 0 的 value 了坷备。
注:該處的map類似于array數(shù)組熄浓,只不過在awk中叫array不恰當(dāng)。
awk Oneline中我們也學(xué)到過省撑,awk 的流程是先判斷表達(dá)式赌蔑,表達(dá)式為真的時(shí)候就執(zhí)行語句俯在,可是我們前面寫的這個(gè) awk 命令里只有表達(dá)式,沒有語句娃惯,那我們執(zhí)行什么呢跷乐?原來,當(dāng)語句被省略的時(shí)候趾浅,awk 就執(zhí)行默認(rèn)的語句愕提,即打印整個(gè)完整的當(dāng)前行。就這樣皿哨,我們通過這個(gè)非常簡短的 awk 命令實(shí)現(xiàn)了去除重復(fù)行并保留原有文件順序的功能揪荣。
-------------------------------------------------------------------------------------
awk '!x[$0]++' shareprofile.txt > shareprofile_awk.txt
-------------------------------------------------------------------------------------
舉個(gè)最簡單的例子:awk '1' file和awk '{print $0}' file是一個(gè)道理,都是從頭到尾依次打印文件的每一行
基礎(chǔ)知識(shí)就這些往史,如果底太潮去man awk或者google找吧仗颈。
'!a[$0]++'
分成幾個(gè)部分簡單解釋下吧
這個(gè)命令沒有{action}也就是說,只要pattern部分判斷值為真(非0)就打印正行椎例,否則就跳過不打印
挨决!在awk是取相反的意思,就是把對(duì)的變成錯(cuò)的把真的變成假的订歪,放在這個(gè)命令中是神馬作用一會(huì)解釋
a[$0]這個(gè)非常好理解脖祈,建立數(shù)組a其變量是文本中的每一行,awk里$1是第一列刷晋,$2是第二列盖高,以此類推$NF是最后一列,而$0是代表所有列及分隔符眼虱,也就是一整行喻奥,這樣如果pattern是真的那就打印一整行
++的意思是a數(shù)組取變量完畢后,對(duì)該數(shù)組值+1
找個(gè)最簡單的文檔來解釋一下
復(fù)制內(nèi)容到剪貼板
代碼:
cat file
xxx
yyy
xxx
zzz
這個(gè)文件有4行捏悬,其中第一撞蚕、三行是重復(fù)的。套用這個(gè)命令處理流程如下
獲取第一行a[xxx]过牙,因?yàn)檫@是第一行甥厦,數(shù)組a里從沒見過xxx這個(gè)變量,那么自然他的值就是假(0)也就是說a[xxx]=0寇钉,這個(gè)時(shí)候刀疙!就有大作用了,他把a(bǔ)[xxx]假(0)變成了a[xxx]為真(!0)這個(gè)時(shí)候原本不改打印的第一行就變成了應(yīng)該打印了扫倡,取邏輯反后對(duì)a[xxx]的值+1然后處理第二行
第二行a[yyy]這個(gè)情況跟剛才第一行的a[xxx]一樣谦秧,也應(yīng)該打印他
到第三行的時(shí)候情況遍了,因?yàn)榈谝恍幸呀?jīng)出現(xiàn)過了a[xxx]并且已經(jīng)++過了他的值已經(jīng)是非0而不是前兩行的0了,本應(yīng)打印但這時(shí)候再由油够!取邏輯反就不必打印了
第四行a[zzz]就又和第一蚁袭、二兩行一樣了征懈。
所以執(zhí)行完就是這個(gè)結(jié)果
awk '!a[$0]++' file
xxx
yyy
zzz
再把file搞稍微復(fù)雜點(diǎn)
復(fù)制內(nèi)容到剪貼板
代碼:
awk '{print NR,$0}' file
1 xxx
2 yyy
3 zzz
4 xxx
5 yyy
6 zzz
7 xxx
8 yyy
9 zzz
一共9行文本石咬,3行一次重復(fù)。為了看得更清楚卖哎,本來默認(rèn)的{print $0}稍微改下鬼悠,變成{print NR(行號(hào)),$0}。
那么現(xiàn)在來執(zhí)行下剛才講的試試看
復(fù)制內(nèi)容到剪貼板
代碼:
awk '!a[$0]++{print NR,$0}' file
1 xxx
2 yyy
3 zzz
復(fù)制內(nèi)容到剪貼板
代碼:
awk 'a[$0]++{print NR,$0}' file
4 xxx
5 yyy
6 zzz
7 xxx
8 yyy
9 zzz
很明顯了吧亏娜,有焕窝!的命令是只打印第一次出現(xiàn)的$0也就是去除重復(fù)咯,而沒有维贺!的命令正好跟他相反它掂,就是僅僅去除第一次出現(xiàn)的$0