Ist es möglich, mithilfe regulärer Ausdrücke bestimmte wiederholte Zeichen aus einer Liste zu entfernen?

Ist es möglich, mithilfe regulärer Ausdrücke bestimmte wiederholte Zeichen aus einer Liste zu entfernen?

Ich habe eine Liste mit einer Spalte, die ~ 100 Zeilen enthält, in denen einige Zeilen wiederholt werden, und mein Ziel ist es, eineSpezifischZeilen duplizieren und nureinskopieren, während die anderen Zeilen unverändert bleiben.

Ein Auszug der Dateien, an denen ich arbeite:

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)

Mein Ziel besteht darin, alle doppelten Zeilen zu entfernen, die C(Xx0-9) enthalten, eine davon zu belassen und V(Xxx..) beizubehalten.

Das Ergebnis, das ich suche:

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)

Ich habe den Befehl verwendet:

sed '0,/C(Mn9)/{/C(Mn9)/d}' inputfile.txt | sed '0,/C(Mn6)/{/C(Mn6)/d}'

und es funktioniert, ist aber nicht gut genug für die ganze Datei, da viel C(Xx1-50) vorhanden ist. Ich dachte daran, reguläre Ausdrücke zu verwenden, aber ich weiß nicht wie, deshalb brauche ich Ihre Hilfe.

Antwort1

$ 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)

Das Obige setzt voraus, dass Sie in Ihrer Beispieleingabe keine Leerzeichen vor/nach den sichtbaren Zeichen haben. Wenn ja, entfernen Sie sie, z. B.:

$ 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)

Antwort2

Ich schlage vor, sedZeilen im Wartebereich zu sammeln, um zu prüfen, ob sie schon einmal vorkamen:

 sed -n 'H;G;/^\(C([^)]*)\).*\1 *\n/!P'
  • Hhängt die aktuelle Zeile an den Haltebereich an
  • Ghängt den Haltebereich mit allen Zeilen, die wir je gesehen haben, an den Musterbereich an
  • C([^)]*)ist eines dieser C(…)Muster, das ^es am Anfang der Zeile verankert und von umgibt \(…\), sodass es später als zurückverwiesen werden kann \1. Wir brauchen \1 *\nein Muster mit der neuen Zeile (nach möglichen Leerzeichen), um zu vermeiden, dass die frisch angehängte Zeile am Ende übereinstimmt. Das gesamte Muster /^\(C([^)]*)\).*\1 *\n/stimmt also mit einer Zeile mit einem doppelten überein C(…), also nur, wenn dies !nicht übereinstimmt,
  • Palles vor dem ersten Zeilenumbruch ausgeben (= ohne das angehängte Leerzeichen), während die Standardausgabe durch die -nOption

Beachten Sie, dass dies je nach sedVersion und Dateigröße fehlschlagen kann, da sich mit der Zeit alle Zeilen im Speicher befinden.

verwandte Informationen