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

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

在这里,我想要类似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

答案1

在支持它的终端上,您可以使用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

输出

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

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

在不支持它的罕见终端上,您始终可以使用光标定位序列,

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

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

答案2

几个月前我在 StackOverflow 上回答了这个问题,请参阅覆盖最后一个终端输出(多行)。虽然我想是这样可能的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

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

restore=$(tput sc)
[[ -z "$restore" ]] && restore=$(tput cuu 4)
[[ -z "$restore" ]] && restore=$(tput cuu1; tput cuu1; tput cuu1; tput cuu1)

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

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

鉴于这是 bash,echo "line1"等实际上应该是一个函数(这将消除多余的tput el调用)。

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

  • DECSC/ DECRC(由 xterm 支持 - 请参阅XTerm 控制序列):

    ESC 7     Save Cursor (DECSC).
    ESC 8     Restore Cursor (DECRC).
    
  • ANSI.SYS(xterm 也支持,但并非所有“xterm 模拟器”都支持):

    CSI s     Save cursor (ANSI.SYS), available only when DECLRMM is disabled.
    CSI u     Restore cursor (ANSI.SYS).
    

其他有用的信息来源:

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

   change_scroll_region          csr        cs        change region to      
                                                      line #1 to line #2    
                                                      (P)   

相关内容