Ich habe einige Dateien im Format
Y15-SUB-B04-P17-BK_M02734_4_000000000-ANNUF_1_1111_24724_4878;size=1;
Y15-SUB-B05-P22-LM_M02734_4_000000000-ANNUF_1_1111_20624_14973;size=1;
Y15-SUB-B05-P22-LM_M02734_4_000000000-ANNUF_1_1103_11326_10379;size=1;
Ich möchte jedes Vorkommen des Unterstrichs (_) durch einen Doppelpunkt (:) ersetzen, AUSSER dem ersten. Ich möchte eine Ausgabe wie diese:
Y15-SUB-B04-P17-BK_M02734:4:000000000-ANNUF:1:1111:24724:4878;size=1;
Y15-SUB-B05-P22-LM_M02734:4:000000000-ANNUF:1:1111:20624:14973;size=1;
Y15-SUB-B05-P22-LM_M02734:4:000000000-ANNUF:1:1103:11326:10379;size=1;
sed -i '' 's/_/:/g' old_file
Ich weiß, dass ich ALLE (oder ) ersetzen kann sed 's/_/:/g' old_file > new_file
und dass ich Zahlen hinzufügen kann, um nur das 2., 4. oder so Vorkommen zu ersetzen:
sed 's/_/:/2' old_file > new_file
Aber wie ersetzt man jedes Vorkommen in jeder Zeile AUSSER dem ersten?
Antwort1
Verwendung von GNU sed
(andere Versionen verhalten sich möglicherweise anders, dankeGlenn Jackman):
sed -i'' 's/_/:/2g' file
Dadurch wird alles so geändert, _
dass :
das erste Vorkommen in jeder Zeile übersprungen wird.
Antwort2
Wir verwenden Posix-sed
ausschließlich Konstrukte wie:
$ sed -e '
y/_/\n/
s/\n/_/
y/\n/:/
' inp.file
Basierend auf den Vorschlägen von Stephane folgen hier noch einige weitere Methoden:
$ perl -pe 's/(^\G.*?_)?.*?\K_/:/g' inp.file
$ perl -pe 'my $n; s/_/$n++?":":$&/ge' inp.file
$ perl -pe 's/_\K(.*)/$1 =~ y|_|:|r/e' inp.file
Antwort3
Ist awk okay? Sie könnten es _
als Feldtrennzeichen verwenden und ausdrucken:
<field 1>_<field 2>:<field n>:<field n+1>:...
So was:
awk -F_ '{ printf("%s_%s", $1, $2); for (x = 3; x <=NF; x++) { printf(":%s", $x); }; printf("\n"); }'
Wenn der Aufbau in allen Zeilen gleich ist, könnte man zur Vermeidung der Schleife die Anzahl der Felder fest codieren (läuft laut einem sehr groben Vorversuch in ca. 2/3 der Zeit):
awk -F_ '{printf("%s_%s:%s:%s:%s:%s:%s:%s\n", $1, $2, $3, $4, $5, $6, $7, $8);}'
Antwort4
Hier ist ein weiteres einfaches awk
Skript (Standard-Linux gawk
), ohne Schleifen:
cat script.awk
match($0,/^[^_]*_/,a){ # match current line to first _ (including) into a[0] variable
sub(a[0],""); # remove a[0] from current line
gsub("_",":"); # replace all _ to : in current line
print a[0]""$0; # output a[0] and current line
}
laufen:
awk -f script.awk input.txt
oder:
awk 'match($0,/^[^_]*_/,a){sub(a[0],"");gsub("_",":");print a[0]""$0;}' input.txt