正規表現を使用してリストの特定の繰り返し文字を削除することは可能ですか?

正規表現を使用してリストの特定の繰り返し文字を削除することは可能ですか?

1列のリストには約100行が含まれており、一部の行は重複しています。私の目的は、特定の行を重複して残す1つ他の行はそのままにして、コピーします。

私が作業中のファイルの抜粋:

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) を含む重複行をすべて削除し、そのうちの 1 つを残して、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必要です。したがって、パターン全体は重複した を含む行に一致するため、これが一致しない場合にのみ、\1 *\n/^\(C([^)]*)\).*\1 *\n/C(…)!
  • P最初の改行の前のすべてを出力します(=追加されたホールドスペースなし)。デフォルトの出力は-nオプションによって抑制されます。

バージョンとファイル サイズによってはsed、時間の経過とともにすべての行がメモリ内に存在するため、失敗する可能性があることに注意してください。

関連情報