如何在终端中向上滚动光标以打印字符串?

Yun*_*nus 4 bash terminal

在这里,我想要一些类似于aircrack-ng在终端屏幕中显示文本的方式,或者像矩阵脚本......!

例如,如果我的终端屏幕已经包含 4 行,我想更新第一行的第一行,其他行也一样......(使用 bash)

更准确地说,我想要一个如下所示的脚本:

#!/bin/bash
while :
  do
    echo "line1"
    echo "line2"
    echo "line3"
    echo "line4"
    # without using clear cmd, next cycle line1 should be printed
    # in line1 place not in a new line , and same for other lines
  done
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 13

在支持它的终端上,您可以使用tput sc保存光标位置并tput rc恢复它:

i=0
tput sc
while sleep 1; do
  tput rc
  echo "line$((i=i+1))"
  echo "line$((i=i+1))"
  echo "line$((i=i+1))"
  echo "line$((i=i+1))"
done
Run Code Online (Sandbox Code Playgroud)

输出

您可以将这些转义序列保存在一个变量中,以避免tput每次都调用:

rc=$(tput rc) ||
  echo >&2 "Warning: terminal doesn't support restoring the cursor"
...
printf '%s\n' "${rc}line1..."
Run Code Online (Sandbox Code Playgroud)

在少数不支持的终端上,你可以随时使用光标定位序列,

while sleep 1; do
  echo "line$((i=i+1))"
  echo "line$((i=i+1))"
  echo "line$((i=i+1))"
  echo "line$((i=i+1))"
  tput cuu 4 # or up=$(tput cuu1); printf %s "$up$up$up$up"
done
Run Code Online (Sandbox Code Playgroud)

有关terminfo更多详细信息,请参阅第 5 节中的手册页(如果您的系统附带 ncurses)。

  • @muru `infocmp -L1 "$terminal" | grep save_cursor` 或 `TERM=$terminal tput sc > /dev/null`。您可以遍历 /usr/share/terminfo 中的终端。 (3认同)
  • 这在输出滚动终端时不起作用;`tput sc` 是绝对的,而不是相对的。 (2认同)

Tho*_*key 5

几个月前我在 StackOverflow 上回答了这个问题,请参阅Overwriting last terminal output(multiple lines)。虽然我认为OP可能意味着打印字面上的“line1”、“line2”等,但这只会在课堂练习中感兴趣。真正的程序打印出更多有趣的东西,所以我来回答这个问题。和以前一样,当更新的行比现有的行短时,当前的 q/a 忽略了这个问题。解决这个问题

#!/bin/bash
tput sc
while :
  do
    tput rc
    echo "line1"; tput el
    echo "line2"; tput el
    echo "line3"; tput el
    echo "line4"; tput el
    # without using clear cmd, next cycle line1 should be printed
    # in line1 place not in a new line , and same for other lines
  done
Run Code Online (Sandbox Code Playgroud)

同意这cuu是一个很好的选择,grep用于检查功能的可用性似乎不如使用tput自身有效,例如,

restore=$(tput sc)
[[ -z "$restore" ]] && restore=$(tput cuu 4)
[[ -z "$restore" ]] && restore=$(tput cuu1; tput cuu1; tput cuu1; tput cuu1)
Run Code Online (Sandbox Code Playgroud)

在表达式中嵌入行数的方式仍然有点粗糙。但是你可以$restore在循环结束时执行。

可以通过el终端中的检查来完成类似的操作。

鉴于这是 bash, theecho "line1"等应该真的是一个函数(这将消除冗余tput el调用)。

OP 可能会遇到的终端可能会支持所有这些功能。保存/恢复光标控件是一个弱点,因为有两个主要变体:

其他有用的信息来源:

顺便说一下,这个问题的标题有误,因为给出的示例(到目前为止没有任何答案)使用scrolling。可以(再次参考 terminfo,并将自己限制为类似 VT100 的终端,例如 xterm)使用滚动区域。开始的地方是这里(来自 terminfo 手册页):

   change_scroll_region          csr        cs        change region to      
                                                      line #1 to line #2    
                                                      (P)   
Run Code Online (Sandbox Code Playgroud)