Incrementar índice en archivo

Incrementar índice en archivo

Muy bien, parece que no puedo encontrar una manera de hacer lo que necesito.

Digamos que tengo un archivo de texto A como este

(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])

etcétera. Quiero cambiar el índice entre corchetes [] de modo que cada índice i sea = i+3.

Lo intenté con una combinación de bucle for y sed, pero no funcionó.

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

done

El problema es que cambiará los primeros 27 por 30 pero en próximas interacciones encontrará 2 bloques con índice 30 (el cambiado y el original).

¿Cómo puedo hacerlo sin sobrescribir los índices ya modificados?

Ok, gracias, edito mi pregunta para mejorar: ¿Cómo puedo hacer algo similar si tengo 2 índices como:

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

¿Y quiero incrementar solo el segundo índice ignorando el primero?

Respuesta1

Utilice Perl:

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

Explicación:

  • -psignifica recorrer cada línea e imprimir el resultado después de cada línea
  • -edefine la expresión a ejecutar en cada línea
  • s/from/to/hace una simple sustitución
  • s/(\d+)/$1+1/gecoincide con uno o más dígitos, los captura en $1y luego el emodificador al final le dice a Perl que la cadena de sustitución es una expresión: $1+1sustituye el valor de $1más 1. El gmodificador significa hacer esta sustitución globalmente, es decir, más de una vez por línea.
  • (?<=\[)es una afirmación positiva de longitud cero. Eso significa que lo que viene después solo coincide si está precedido por [(que debe tener un carácter de escape, \ya que [es un token especial en las expresiones regulares). Lo de la longitud cero significa que no es parte de lo que será reemplazado.
  • (?=\])es una afirmación positiva de anticipación de longitud cero. Eso significa que lo que viene antes solo coincide si va seguido de ](nuevamente escapó).

Entonces esto tomará todos los números entre [y ]e incrementará ese número.

Respuesta2

También podrías usar awk:

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

De hecho, esto se puede reducir ligeramente a:

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

Respuesta3

Sé que ya resolvió su problema, pero para su información, podría haberlo resuelto con una modificación muy simple de su código: invirtiendo la secuencia que recorre.

Usar {107..27..-1}(o más concisamente {107..27}) hubiera sido suficiente para solucionar tu problema, ya que al reemplazar 30 solo se habrían encontrado los 30 originales, no habiendo sido reemplazados los 27 aún.

Respuesta4

Ok, creo que tengo una solución para el doble índice y también modifico el comando de cas. Esto hace que el trabajo:

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

Por cierto, no estoy seguro de por qué necesito . ($1) .(punto con espacio en blanco).

información relacionada