Você pode usar apenas sed para fazer a correção para você:
printf '%s\n' "$i" "$j" |
sed 's/[]\$*&/.^[]/\&/g;H;$!d
x;y|\n|/|;s|.*|s&/g|' |
sed -f - /path/to/infile
Portanto, este s/// ubstitution irá escapar de todos / quaisquer metacaracteres do BRE na entrada:
s/[]\$*&/.^[]/\&/g
... prefixando cada um com uma barra invertida. O primeiro sed , em seguida, salva uma cópia da primeira linha - $i - em H old space, adicionando um caractere \n ewline a ele. A linha $i é então d eletida porque é ! não a $ anterior. A próxima linha - a $j line - também é a última, e depois de receber o mesmo tratamento da primeira, ela não é d eleted. Em vez disso, ele e x altera os buffers de retenção e padrão e opera nos resultados concatenados. Neste ponto, o espaço padrão é semelhante:
\n1\.0\n2\.0
... por isso, y/// traduz todos os \n ewlines para / slashes, s/// ubstitute .* todo o espaço padrão para & em si, mais um s pré-anexado e um% anexado/g que nos leva:
s/1\.0/2\.0/g
Isso é automaticamente impresso para o segundo sed que está lendo stdin - ou -f - - como seu script. Quando o primeiro sed for concluído e fechar o pipe entre eles, o segundo sed começará a aplicar ...
s/1\.0/2\.0/g
... para cada linha em seu arquivo de entrada nomeado - que está aqui /path/to/infile .
Eu escrevi seu arquivo assim:
printf '%04s%04s%04s%04s\n' \
0 0 -1 0 1 0 0 0 0 -1\
0 0 1.5 2.0 1.0 0 >/tmp/temp
O que me deu um arquivo como ...
0 0 -1 0
1 0 0 0
0 -1 0 0
1.5 2.0 1.0 0
Eu então escrevi uma versão diferente do seu script como:
ii=0.0
for i in 1.0 2.0 3.0 4.0
do str2=$i
printf '3[41m## %s 3[0m\n' \
"str2 = $str2" "$ii $str2"
printf %s\n "$ii" "$str2"
ii=$str2
done |
sed ' s/[]\$^&*./[]/\&/g;H;x
s|^\(\n\)\(.*\)\n\(.*\)\n\(.*\)\n\(.*\)|\
bs:ii\\:ss///gp;ti|p
s|||;h;d' |
sed -f - /tmp/temp
O qual usa o shell apenas para gerar as strings, mas permite que sed faça todo o processamento de dados. Observe que, embora dois sed s sejam chamados, cada um deles é chamado apenas uma vez.
Quando eu executo, os resultados são:
0 0 -1 0
1 0 0 0
0 -1 0 0
1.5 2.0 2.0 0
## str2 = 2.0
## 1.0 2.0
1.5 3.0 3.0 0
## str2 = 3.0
## 2.0 3.0
1.5 4.0 4.0 0
## str2 = 4.0
## 3.0 4.0
1.5 4.0 4.0 0
As linhas que começam com # são coloridas em vermelho como espero que você queira que sejam. sed apenas os grava quando uma s/// ubstitution for bem-sucedida. O script que o primeiro sed escreve para o segundo se parece com:
bs1\.0
:i1\.0
i\
[41m## str2 = 1\.0 [0m\
[41m## 0\.0 1\.0 [0m
:s1\.0
s/0\.0/1\.0/gp;ti1\.0
bs2\.0
:i2\.0
i\
[41m## str2 = 2\.0 [0m\
[41m## 1\.0 2\.0 [0m
:s2\.0
s/1\.0/2\.0/gp;ti2\.0
bs3\.0
:i3\.0
i\
[41m## str2 = 3\.0 [0m\
[41m## 2\.0 3\.0 [0m
:s3\.0
s/2\.0/3\.0/gp;ti3\.0
bs4\.0
:i4\.0
i\
[41m## str2 = 4\.0 [0m\
[41m## 3\.0 4\.0 [0m
:s4\.0
s/3\.0/4\.0/gp;ti4\.0
Note que embora pareça que as sequências de [ não são ignoradas, este é apenas o efeito do meu terminal na saída - que acaba comendo o caractere imediatamente após 3 . Quando o segundo sed receber o script, a entrada será como 3\[... , mas a saída i nsert para stdout será 3[...