是否可以使用正規表示式刪除清單中的特定重複字元?

是否可以使用正規表示式刪除清單中的特定重複字元?

我有一個列的列表,其中包含約 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版本和檔案大小,這可能會失敗,因為隨著時間的推移,所有行都將儲存在記憶體中。

相關內容