Eu sei que isso não é uma boa coisa a fazer e/ou uma boa solução, mas eu estava apenas brincando tentando responder a essa pergunta e me deparei com o seguinte problema.
O objetivo é ler o arquivo de entrada caractere por caractere e se o caractere estiver dentro do intervalo especificado, substitua-o.
Entrada:
NNNNN
NNNNN
NNNNN
NNNNN
Roteiro:
#!/bin/bash
#set -x
input=~/tmp/in
declare -i count=0
low=$1
high=$2
new_char=$3
while IFS=$'\n' read -r line; do
while IFS= read -rn1 char; do
if ((count>=low)) && ((count<=high)); then
printf '%s' "$new_char"
else
printf '%s' "$char"
fi
((count++))
done <<<"$(printf '%s' "$line")"
echo
done <"$input"
Saída desejada (quando executado como: ./script.sh 10 13 P
):
NNNNN
NNNNP
PPPNN
NNNNN
Saída real:
$ ./script.sh 10 13 P
NNNNN
NNNNPP
PPNNN
NNNNN
Não sei por que aparentemente está criando um novo personagem do nada na 2ª linha e não substituindo o 13º personagem na 3ª linha. Eu tentei mover a ((count++))
instrução para o início do segundo loop while, tentei iniciar em count=1
, tentei aparentemente todas as combinações de ((++count))
|| count=$((count+1))
|| ((count+1))
. Com resultados variados, mas todos parecem adicionar um caractere extra na segunda linha.
Verifiquei duas vezes se o arquivo de entrada não possui espaços em branco à direita em nenhuma das linhas.
Eu escreveria:
Aqui Strings parecem produzir uma nova linha no final:
Você pode tentar e ver a diferença:
Então, você deve usar
< <(printf '%s' "$line")
em vez de<<<"$(printf '%s' "$line")"
.