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:
-p
significa fazer um loop em cada linha e imprimir o resultado após cada linha-e
define a expressão a ser executada em cada linhas/from/to/
faz uma substituição simpless/(\d+)/$1+1/ge
corresponde a um ou mais dígitos, captura-os em$1
e então oe
modificador no final diz ao Perl que a string de substituição é uma expressão:$1+1
substitui o valor de$1
mais 1. Og
modificador 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).