shell命令技巧 文字去重並保持原有順序

2022-07-27 16:12:24 字數 2065 閱讀 4946

簡單來說,這個技巧相應的是例如以下一種場景

假設有文字例如以下

cccc

aaaa

bbbb

dddd

bbbb

cccc

aaaa

如今須要對它進行去重處理。這個非常easy,sort -u就能夠搞定,可是假設我希望保持文字原有的順序。比方這裡有兩個aaaa,我僅僅是希望去掉第二個aaaa,而第乙個aaaabbbb的前面。去重後仍舊要在它前面。所以我期望的輸出結果是

cccc

aaaa

bbbb

dddd

當然,這個問題本身並不難。用c++或python寫起來都非常easy,但所謂殺機焉用牛刀,能用shell命令解決時。它永遠都是我們的首選。答案在最後給出。以下說說我是怎樣想到這樣

我們有時候想把自己的資料夾增加環境變數path時會在~/.bashrc檔案裡這樣寫,比方待增加的資料夾為$home/bin

export path=$home/bin:$path
這樣我們等於是在path追加了路徑$home/bin並讓它在最前面被搜尋到。但當我們執行source ~/.bashrc後,$home/bin資料夾就會被增加path,假設我們下次再增加乙個資料夾,比方

export path=$home/local/bin:$home/bin:$path
再執行source ~/.bashrc時,$home/bin資料夾在path中事實上會有兩份記錄。儘管這不影響使用。但對於乙個強迫症來說,這是無法忍受的。於是問題就變成了,我們須要去掉$path裡反覆的路徑,而且保持原有路徑順序不變,也就是原本誰在前面。去重後仍舊在前面,由於在執行shell命令時是從第乙個路徑開始查詢的。所以順序非常重要

好了。說了這麼多我們來揭示終於的結果。以文章開始的資料為例,假設輸入檔案是in.txt。命令例如以下

cat -n in.txt | sort -k2,2 -k1,1n | uniq -f1 | sort -k1,1n | cut -f2-
這些都是非常easy的shell命令,以下稍作解釋

cat -n in.txt : 輸出文字,並在前面加上行號。以\t分隔

sort -k2,2 -k1,1n : 對輸入內容排序,primary key是第二個字段,second key是第乙個字段而且按數字大小排序

uniq -f1 : 忽略第一列。對文字進行去重,但輸出時會包括第一列

sort -k1,1n : 對輸入內容排序,key是第乙個欄位並按數字大小排序

cut -f2- : 輸出第2列及之後的內容。預設分隔符為\t

大家能夠從第一條命令開始,並依次組合。看看實際輸出效果,那樣便更easy理解了。對於$path中的反覆路徑又該怎樣處理呢。還是曾經面的樣例來說,僅僅需在前後用tr做一下轉換就可以

export path=$home/local/bin:$home/bin:$path

export path=`echo $path | tr ':' '\n' | cat -n | sort -k2,2 -k1,1n | uniq -f1 | sort -k1,1n | cut -f2- | tr '\n' ':'`

事實上這樣使用path會有個問題,比方我們執行了以上命令後。假設想去掉$home/bin這個路徑。僅僅改動為例如以下內容是不夠的

export path=$home/local/bin:$path

export path=`echo $path | tr ':' '\n' | cat -n | sort -k2,2 -k1,1n | uniq -f1 | sort -k1,1n | cut -f2- | tr '\n' ':'`

由於我們已經將$home/bin增加了$path中,這樣做並沒有起到刪除的作用,或許最好的方式還是自己清楚的知道全部路徑,然後顯示指定,而不是採取追加的方式

finger print 文字去重

任何一段資訊文字,都可以對應乙個不太長的隨機數,作為區別它和其它資訊的指紋 fingerprint 只要演算法設計的好,任何兩段資訊的指紋都很難重複,就如同人類的指紋一樣。資訊指紋在加密 資訊壓縮和處理中有著廣泛的應用。string content2 卓爾防線繼續傷筋動骨 隊長梅方出場再補漏說起來卓...

資料 文字去重

先排序,後取重 sort file.txt uniq usr bin python coding utf 8 import sys reload sys sys.setdefaultencoding utf 8 def text duplicate byset sourcepath,destpath...

shell不排序去重

一條命令搞定 awk a 0 file 如果是第一次出現a 0 的值為0 假 而 a 0 的值就為1 真 之後就執行print 0 第二次或者兩次以上的出現a 0 的值就為大於0的整數值 真 例如1,2,3.而 a 0 的值就為0 假 之後就不執行print 0操作 awk 0 in a patte...