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[...