Index in Datei erhöhen

Index in Datei erhöhen

Okay, es scheint, als ob ich keine Möglichkeit finde, das zu tun, was ich brauche.

Nehmen wir an, ich habe eine Textdatei A wie diese

(freqBiasL2[27])      
(SatBiasL1[27])       
(defSatBiasL2_L1[27]) 
(defSatBiasSlope[27]) 
(defSatBiasSigma[27]) 

(freqBiasL2[28])      
(SatBiasL1[28])       
(defSatBiasL2_L1[28]) 
(defSatBiasSlope[28]) 
(defSatBiasSigma[28]) 

(freqBiasL2[29])      
(SatBiasL1[29])       
(defSatBiasL2_L1[29]) 
(defSatBiasSlope[29]) 
(defSatBiasSigma[29])

und so weiter. Ich möchte den Index zwischen den Klammern [] so ändern, dass jeder Index i = i+3 ist.

Ich habe es mit einer Kombination aus for-Schleife und sed versucht, aber es funktioniert nicht

for i in {27..107..1}
do
    i_new=$((i+3))
    sed -e 's/\['$i'\]/\['$i_new'\]/' prova.txt 

done

Das Problem besteht darin, dass die ersten 27 durch 30 geändert werden, bei den nächsten Interaktionen jedoch zwei Blöcke mit dem Index 30 gefunden werden (der geänderte und der ursprüngliche).

Wie kann ich das machen, ohne die bereits geänderten Indizes zu überschreiben?

Ok, danke, ich bearbeite meine Frage zur Verbesserung: Wie kann ich etwas Ähnliches tun, wenn ich 2 Indizes habe, wie:

(freqBiasL2[32][100])
(SatBiasL1[32][101])
(defSatBiasL2_L1[32][102])
(defSatBiasSlope[32][103])
(defSatBiasSigma[32][104])

und ich möchte nur den zweiten Index erhöhen und den ersten ignorieren?

Antwort1

Verwenden Sie Perl:

perl -pe 's/(?<=\[)(\d+)(?=\])/$1+1/ge' prova.txt

Erläuterung:

  • -pbedeutet, dass jede Zeile durchlaufen wird und das Ergebnis nach jeder Zeile gedruckt wird
  • -edefiniert den Ausdruck, der in jeder Zeile ausgeführt werden soll
  • s/from/to/macht eine einfache Substitution
  • s/(\d+)/$1+1/gestimmt mit einer oder mehreren Ziffern überein, erfasst sie in $1und dann eteilt der Modifikator am Ende Perl mit, dass die Ersetzungszeichenfolge ein Ausdruck ist: $1+1ersetzt den Wert von $1plus 1. Der gModifikator bedeutet, dass diese Ersetzung global, also mehr als einmal pro Zeile, durchgeführt werden soll.
  • (?<=\[)ist eine positive Lookbehind-Assertion mit der Länge Null. Das bedeutet, dass das, was danach kommt, nur dann übereinstimmt, wenn davor steht (was mit as [maskiert werden muss, einem speziellen Token in regulären Ausdrücken). Die Sache mit der Länge Null bedeutet, dass es nicht Teil dessen ist, was ersetzt wird.\[
  • (?=\])]ist eine positive Lookahead-Assertion mit der Länge Null. Das bedeutet, dass das, was davor steht, nur dann übereinstimmt, wenn darauf (wieder maskiert) folgt .

Dies nimmt alle Zahlen zwischen [und ]und erhöht diese Zahl.

Antwort2

Sie könnten auch verwenden awk:

awk -F '[\\[\\]]' '{if ($2) { sub($2, $2 + 3)}} 1' prova.txt

Tatsächlich kann dies leicht verkürzt werden zu:

awk -F '[\\[\\]]' '$2 { sub($2, $2 + 3)} 1' prova.txt

Antwort3

Ich weiß, dass Sie Ihr Problem bereits gelöst haben, aber zu Ihrer Information: Sie hätten es auch mit einer sehr einfachen Änderung Ihres Codes lösen können: durch Umkehren der Sequenz, die Sie durchlaufen.

Die Verwendung von {107..27..-1}(oder genauer gesagt {107..27}) hätte zur Lösung Ihres Problems ausgereicht, da beim Ersetzen von 30 nur die ursprünglichen 30 gefunden worden wären und die 27 noch nicht ersetzt worden war.

Antwort4

Ok, ich glaube, ich habe auch eine Lösung für den doppelten Index, indem ich den Befehl von cas ändere. Das macht den Job:

perl -p -e 's/\[(\d+)\]\[(\d+)\]/"[" . ($1) . "][" . ($2+40) . "]"/ge' prova.txt

Ich bin mir übrigens nicht sicher, warum ich . ($1) .(Punkt mit Leerzeichen) brauche.

verwandte Informationen