我有一個列的列表,其中包含約 100 行,其中一些行是重複的,我的目的是擺脫具體的重複行並僅保留一複製,而其他行保持不變。
我正在處理的文件的摘錄:
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(Mn9)
C(Mn6)
C(C1)
C(C4)
C(Mn9)
C(Mn6)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)
我的目的是刪除所有包含 C(Xx0-9) 的重複行並保留其中一個並保留 V(Xxx..)。
我尋求的結果:
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(C1)
C(C4)
C(Mn9)
C(Mn6)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)
我使用了命令:
sed '0,/C(Mn9)/{/C(Mn9)/d}' inputfile.txt | sed '0,/C(Mn6)/{/C(Mn6)/d}'
它正在工作,但對於整個文件來說還不夠好,因為有很多 C(Xx1-50),我想使用正則表達式,但我不知道如何,這就是為什麼我需要你的幫助。
答案1
$ awk '!(/^C\(..[0-9])$/ && seen[$0]++)' file
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(Mn9)
C(Mn6)
C(C1)
C(C4)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)
上面假設範例輸入中的可見字元之前/之後沒有空格。如果這樣做,則刪除它們,例如:
$ awk '{gsub(/^[[:space:]]+|[[:space:]]+$/,"")} !(/^C\(..[0-9])$/ && seen[$0]++)' file
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(Mn9)
C(Mn6)
C(C1)
C(C4)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)
答案2
我建議使用sed
收集保留空間中的行來檢查它們之前是否出現過:
sed -n 'H;G;/^\(C([^)]*)\).*\1 *\n/!P'
H
將目前行追加到保留空間G
將保留空間與我們見過的所有行附加到模式空間C([^)]*)
是這些模式之一C(…)
,^
將其錨定到行的開頭,並且它被 包圍\(…\)
,因此可以\1
稍後反向引用。我們需要\1 *\n
作為模式,帶有換行符(在可能的空格之後)以避免匹配末尾新添加的行。因此整個模式/^\(C([^)]*)\).*\1 *\n/
與具有重複項的行匹配C(…)
,因此僅當這!
不匹配時,P
-n
在第一個換行符之前列印所有內容(= 沒有附加的保留空間),而預設輸出被該選項抑制
請注意,根據您的sed
版本和檔案大小,這可能會失敗,因為隨著時間的推移,所有行都將儲存在記憶體中。