方法一:
先sort排序,再去重
:sort //直接排序:g/^\(.*\)$\n\1$/d //去除重複行:g/\%(^\1$\n\)\@<=\(.*\)$/d //功能同上,也是去除重複行:g/\%(^\1\>.*$\n\)\@<=\(\k\+\).*$/d //功能同上,也是去除重複行
方法二:使用awk
awk ‘!a[$0]++’ file
解析:
借用http://bbs.51cto.com/thread-964013-1.html
awk流程是逐行處理的,預設從檔案的第一行一直處理到檔案最後一行,還要知道awk的基本命令格式是'pattern{action}'先匹配各種各樣的樣式,然後大括弧裡處理如何列印輸出,預設的只要匹配了pattern就{print $0},如果pattern未命中其判斷值為假(0)那麼就不會再去處理{action}了;pattern命中則為判斷值為真(非0)就去處理{action}。
舉個最簡單的例子:awk '1' file和awk '{print $0}' file是一個道理,都是從頭到尾依次列印檔案的每一行。
'!a[$0]++'
分成幾個部分簡單解釋下吧。
這個命令沒有{action}也就是說,只要pattern部分判斷值為真(非0)就列印該行,否則就跳過不列印
!在awk是取相反的意思,就是把對的變成錯的把真的變成假的,放在這個命令中是神馬作用一會解釋;
a[$0]這個非常好理解,建立數組a,其變數是文本中的每一行,awk裡$1是第一列,$2是第二列,以此類推$NF是最後一列,而$0是代表所有列及分隔字元,也就是一整行,這樣如果pattern是真的那就列印一整行
++的意思是a數組取變數完畢後,對該數組值+1
找個最簡單的文檔來解釋一下
cat file
xxx
yyy
xxx
zzz
這個檔案有4行,其中第一、三行是重複的。套用這個命令處理流程如下:
擷取第一行a[xxx],因為這是第一行,數組a裡從沒見過xxx這個變數,那麼自然他的值就是假(0)也就是說a[xxx]=0,這個時候!就有大作用了,他把a[xxx]假(0)變成了a[xxx]為真(!0)這個時候原本不該列印的第一行就變成了應該列印了,取邏輯反後對a[xxx]的值+1然後處理第二行
第二行a[yyy]這個情況跟剛才第一行的a[xxx]一樣,也應該列印他
到第三行的時候情況變了,因為第一行已經出現過a[xxx]並且已經++過了,他的值已經是非0而不是前兩行的0了,本應列印但這時候再由!取邏輯反就不必列印了
第四行a[zzz]就又和第一、二兩行一樣了。
所以執行完就是這個結果
awk '!a[$0]++' file
xxx
yyy
zzz
再把file搞稍微複雜點
awk '{print NR,$0}' file1 xxx2 yyy3 zzz4 xxx5 yyy6 zzz7 xxx8 yyy9 zzz
一共9行文本,3行一次重複。為了看得更清楚,本來預設的{print $0}稍微改下,變成{print NR,$0}。 NR表示行號。
那麼現在來執行下剛才講的試試看
awk '!a[$0]++{print NR,$0}' file1 xxx2 yyy3 zzz
awk 'a[$0]++{print NR,$0}' file4 xxx5 yyy6 zzz7 xxx8 yyy9 zzz
很明顯了吧,有!的命令是只列印第一次出現的$0也就是去除重複咯,而沒有!的命令正好跟他相反,就是僅僅去除第一次出現的$0。