2017-02-24 3 views
1

Ich habe das folgende Problem.sed finden und ersetzen für nur bestimmte Anzahl von Vorkommen

Ich habe eine Datei mit Sequenz und ich möchte ein bestimmtes Muster finden und durch ein anderes Muster ersetzen, aber nur für eine bestimmte Anzahl von Malen.

zB:

ABCDEFGHIJKLMN 
ABCDEFGHIJKLMN 
ABCDEFGHIJKLMN 
ABCDEFGHIJKLMN 
ABCDEFGHIJKLMN 
ABCDEFGHIJKLMN 

ich will "DEFGHI" finden und ersetzen sie durch "ABCDEF" für nur 3 mal.

sed -i 's/DEFGHI/ABCDEF/g' /home/user/test.txt 

Ich möchte nicht global ersetzen; stattdessen möchte ich nur 3 mal ersetzen.

+0

Warum wollen Sie 'DEFGHI' mit sich selbst ersetzen? Zeigen Sie Ihre gewünschte Ausgabe an. – toolic

+0

Entschuldigung. Ich möchte mit einem anderen Patten ersetzen. zB: DEFGHI mit ABCDEF – manoj

+0

Dies ist nicht trivial. Kann das Muster mehr als einmal pro Zeile auftreten? – melpomene

Antwort

0

Sie können das erste Vorkommen ersetzen gefunden dreimal:

sed -i '0,/DEFGHI/s//ABCDEF/;0,/DEFGHI/s//ABCDEF/;0,/DEFGHI/s//ABCDEF/' file 

Ausgang:

ABCABCDEFJKLMN 
ABCABCDEFJKLMN 
ABCABCDEFJKLMN 
ABCDEFGHIJKLMN 
ABCDEFGHIJKLMN 
ABCDEFGHIJKLMN 
2

Dieses auf das Suchmuster dreimal ersetzt, je nachdem, wie sie über die Leitungen verteilt sind

perl -0777 -pe'$i += s/DEF/xxx/ while $i < 3' <data.txt> out.txt 

Es wird davon ausgegangen, dass das Muster nicht über die Zeilen unterbrochen ist. Es macht Pässe über die Saite und sucht jedes Mal von Anfang an. Dies kommt mit einer Einschränkung, die unten erklärt wird und ineffizient ist, aber es ist einfach.

Wenn der Ersatz selbst das Muster in Verbindung mit dem umgebenden Text neu erstellt, wird dies auch im nächsten Durchgang ersetzt. Ein solcher Ersatz müsste Teile des Musters selbst und auf spezifische Weise enthalten. Wenn dies jedoch ein Problem ist, lassen Sie es mich wissen.

Die Behandlung möglicher überlappender Muster ist im Problem nicht angegeben. Wenn es eine solche Lösung gibt, wird die erste ersetzt, so dass im nächsten Durchgang die Überlappung verschwunden ist.

+0

Kommentare von @melpomene waren hilfreich, danke – zdim

+0

Die (gelöschte) Antwort von @sidyll hat die richtige Idee und war hilfreich, danke – zdim

+0

danke. es funktionierte wie beabsichtigt .. vielen Dank – manoj

2

Dies kann mit bash erfolgen und GNU sed wie folgt aus:

sed -z -i "$(echo s/DEFGHI/ABCDEF/{3..1}\;)" yourfile 
  • Die {3..1} Ergebnisse in der s Teil mit Flagge drei Mal wiederholt, 3 bis 1. Jeder s Befehl ersetzt nur die dritte, zweites und erstes Auftreten. Die umgekehrte Reihenfolge ist notwendig, damit das Zählen und Ersetzen nicht verwechselt werden kann.
  • -z Takes nimmt alle Eingabezeilen auf einmal, so dass die Zählung nicht pro Zeile, sondern pro Datei erfolgt.

Zu Ihrer Information hier ist das, was der Befehl Substitution um das Echo erzeugt:

echo s/DEFGHI/ABCDEF/{3..1}\; 
> s/DEFGHI/ABCDEF/3; s/DEFGHI/ABCDEF/2; s/DEFGHI/ABCDEF/1; 
+1

@SLePort Sie haben Recht. Ich habe die Reihenfolge umgekehrt. Vielen Dank. –

+0

+1 für die sed + shell-Kombination, die gut für beliebige andere Werte als 3 funktioniert. Diese "geschweifte Erweiterung", um klar zu sein ... bash? Also ist es GNU sed + bash und bashähnliche Shells. – stevesliva

Verwandte Themen