Incrementar índice no arquivo

Incrementar índice no arquivo

Tudo bem, parece que não consigo encontrar uma maneira de fazer o que preciso.

Digamos que eu tenha um arquivo 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])

e assim por diante. Quero alterar o índice entre [] colchetes de modo que cada índice i seja = i+3.

Eu tentei com uma combinação de for loop e sed, mas não funcionou

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

done

O problema é que ele irá trocar os primeiros 27 por 30 mas nas próximas interações encontrará 2 blocos com índice 30 (o alterado e o original).

Como posso fazer isso sem substituir os índices já alterados?

Ok, obrigado, edito minha pergunta para uma melhoria: Como posso fazer algo semelhante se eu tiver 2 índices como:

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

e quero incrementar apenas o segundo índice ignorando o primeiro?

Responder1

Usar perl:

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

Explicação:

  • -psignifica fazer um loop em cada linha e imprimir o resultado após cada linha
  • -edefine a expressão a ser executada em cada linha
  • s/from/to/faz uma substituição simples
  • s/(\d+)/$1+1/gecorresponde a um ou mais dígitos, captura-os em $1e então o emodificador no final diz ao Perl que a string de substituição é uma expressão: $1+1substitui o valor de $1mais 1. O gmodificador significa fazer esta substituição globalmente, ou seja, mais de uma vez por linha.
  • (?<=\[)é uma afirmação lookbehind positiva de comprimento zero. Isso significa que o que vem depois só corresponde se for precedido por [(que precisa ser escapado \como [um token especial em expressões regulares). O comprimento zero significa que não faz parte do que será substituído.
  • (?=\])é uma afirmação antecipada positiva de comprimento zero. Isso significa que o que vem antes só corresponde se for seguido por ](novamente escapado).

Portanto, isso levará todos os números entre [e ]e incrementará esse número.

Responder2

Você também pode usar awk:

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

Na verdade, isso pode ser ligeiramente abreviado para:

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

Responder3

Eu sei que você já resolveu seu problema, mas para sua informação, você poderia tê-lo resolvido com uma modificação muito simples em seu código: invertendo a sequência em que você faz o loop.

Usar {107..27..-1}(ou de forma mais concisa {107..27}) teria sido suficiente para resolver o seu problema, pois ao substituir 30, apenas os 30 originais teriam sido encontrados, não tendo os 27 ainda sido substituídos.

Responder4

Ok, acho que tenho uma solução para o índice duplo, além de modificar o comando do cas. Isso torna o trabalho:

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

A propósito, não sei por que preciso do . ($1) .(ponto com espaço em branco).

informação relacionada