为什么我的脚本会创建一个额外的角色?

为什么我的脚本会创建一个额外的角色?

我知道这不是一件好事和/或一个好的解决方案,但我只是在尝试回答问题,我遇到了以下问题。

目标是逐个字符读取输入文件,如果该字符在指定范围内,则替换它。

输入:

NNNNN
NNNNN
NNNNN
NNNNN

脚本:

#!/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"

所需的输出(当运行时:)./script.sh 10 13 P

NNNNN
NNNNP
PPPNN
NNNNN

实际输出:

$ ./script.sh 10 13 P
NNNNN
NNNNPP
PPNNN
NNNNN

我不知道为什么它似乎在第二行凭空创建了一个新角色,而不是替换第三行的第 13 个角色。我尝试将((count++))语句移动到第二个 while 循环的开头,我尝试从 开始count=1,我尝试了似乎((++count))||的所有组合count=$((count+1))|| ((count+1))。结果各不相同,但似乎都在第二行添加了一个额外的字符。

我已经仔细检查过输入文件的任何行上都没有尾随空格。

答案1

这里字符串似乎在末尾产生一个换行符:

你可以尝试看看有什么不同:

cat <<<"test"
cat <(printf '%s' "test")

因此,您应该使用 < <(printf '%s' "$line")而不是<<<"$(printf '%s' "$line")".

答案2

我会写:

while IFS= read -r line; do
    for ((i=0; i<${#line}; i++)); do
        char=${line:i:1}
        ((count++))
        ((low <= count && count <= high)) && char=$new_char
        printf '%s' "$char"
    done
    echo
done <"$input"

相关内容