为什么在使用 tput el1 时需要 \r

Why \r required when using tput el1

中创建倒数计时器时,我想到了以下代码:

for ((n=15; n > 0; n--)); do
    printf "Reload |  $n" && sleep 1
done

这很好用,它不断将 printf 添加到同一行,正如预期的那样。


所以我在 tput 上打开了 documentation 并发现:

tput el1

Clear to beginning of line

并试了一下:

for ((n=15; n > 0; n--)); do
    tput el1; printf "Reload |  $n" && sleep 1
done

但是,这会在每次迭代时添加一个选项卡,因此输出变为:

Reload | 15
            Reload | 14
                        Reload | 13

这些输出在同一行,所以 'clear' 有效,但由于某种原因,光标没有恢复到第一列。


我已经通过在 printf:

后面添加回车符 return (\r) 来修复它
for ((n=15; n > 0; n--)); do
    tput el1; printf "Reload | $n\r" && sleep 1
done

我已经阅读了很多文档,但不明白为什么这里需要 \r。关于这件事请指点我右边documentation/duplicate

比较el1

tput el1
    Clear to beginning of line

clear

tput clear
    clear screen and home cursor

注意 clear 明确指出它移动光标; el1 没有。它 擦除行首和当前光标位置之间的当前行上的任何内容,将光标留在后面文本所在的位置。

另一方面,回车 return 通常被解释为将光标移动到当前行的开头而不前进到下一行。对应的终端能力为cr.

一个更稳健的解决方案是先移动光标,然后清除到行的 end,最后输出下一段文本。这处理了新文本比之前文本短的情况,当您从 double-digit 切换到 single-digit 数字时,这将是一个问题。

for ((n=15; n>0; n--)); do
  tput cr el; printf "Reload |  %2d" "$n"; sleep 1
done

%2d 是为了确保 single-digit 值不会向左“跳转”一个 space。)