是的。

是的。

我想将光标定位在特定的行/列并打印一个与其第一个坐标保持对齐的多行文件/命令,以便

tput clear
tput cup 5 15
ping www.google.com

将输出第 15 列中的所有后续行。事实上,第一行打印正确,但后面的行被重置到左侧。是否可以使用tput或任何其他方法?

答案1

一种方法是在该位置设置制表位:

trap 'tabs -8' EXIT INT TERM # restore to default tab stops every 8 columns
                             # upon exit or signal

tput tbc # clear tab stops
tput cup 5 15
tput hts # set one and only tab stop
printf '\r' # move back to the beginning of the line
printf '\t%s\n' foo bar baz
ping www.google.com | paste /dev/null -

这确实会影响终端的行为,例如在暂停时可能会导致问题。

相对于 @Thorcup基于方法的优点是,它发送的输出更少(除非您使用 300 波特率的卫星链路,否则并不是真正的问题),并且如果 syslog 等其他进程也在向终端写入文本,则其行为会更加优雅。

确保每行从位置 15 开始的另一种方法是为每行添加前缀\r$(tput cuf 15)

tput cup 5 15
ping www.google.com | PREFIX=$(tput cr; tput cuf 15) awk '
  {print ENVIRON["PREFIX"] $0}'

另请参阅csr设置滚动区域的功能。

如果使用zsh,另请参阅其zcurses builtin

答案2

是的。

...不需要对相关程序的输出进行后处理,或者让它改变其行为,因为它认为它正在与管道而不是终端字符设备通信(正如某些程序确实所做的那样)。

tput无法执行此操作,因为没有提供必要功能的 terminfo 功能。而且,这个功能是具体的特定类别的终端,即那些实现 DEC VT 系列终端中的多个控制序列的终端。

但它可能的。

那是少量的终端。对于终端仿真器来说,仿真 DEC VT 及其控制序列是一件很流行的事情。但并非所有终端仿真器都能理解并实现为此所需的特定 DEC VT 控制序列。确实包括:

此类终端具有可设置的 DEC VT 概念边距。页边距控制正常输出的滚动和自动页边距换行行为。终端还具有 DEC VT 概念:原点模式。这是一个模式设定当设置时, 使利润使用 CUP 和 HVP 控制序列控制绝对光标定位。最后,他们实施全部的利润,包括后来的 DEC VT 型号提供的新利润。

因此,当您的程序启动或继续时:

  • 通过发出 DECSTBM 控制序列来设置顶部和底部边距。
  • 通过开启DECLRMM模式启用左右边距机制
  • 通过发出 DECSLRM 控制序列来设置左右边距。
  • 开启DECOM模式
  • 将光标归位,以防万一打开原点模式时光标超出边距,并且打开原点模式不会自动移动光标。

当程序退出、暂停或终止时,执行相反的操作即可将屏幕恢复正常。您还需要保持行规则中保存的有关终端大小的信息正确,以便使用光标寻址模式的程序知道边距区域的大小而不是整个屏幕的大小。

第一次,会是这样的

printf '\e[%d;%dr\e[?69h\e[%d;%ds\e[?6h\e[H' 5 20 5 65
stty 行 15 列 60
ping www.google.com
printf '\e[?6l\e[s\e[?69l\e[r'
stty 行 25 列 80
尽管您应该在面对脚本被终止时极大地改进其清理行为,并且更聪明地将行规则中的行和列恢复到正确的值(而不是像我为了简洁起见所做的那样做出错误的假设)。

对于较少的功能,这些终端模拟器尊重顶部和底部边距,但没有您在此处特别需要的左右边距机制:

  • 乌尔克斯VT
  • 康索尔
  • 术语
  • 油灰

请注意,必须为主屏幕缓冲区和备用屏幕缓冲区单独设置边距。因此,在切换到光标寻址模式时切换到备用屏幕缓冲区的程序将不会受此影响。该组包括 NeoVIM 等程序以及更少的程序。进行光标寻址的程序没有但是,将切换到备用屏幕缓冲区。后一组包括 Z shell 中的 ZLE 之类的东西。

进一步阅读

答案3

简短回答:不。

tput cup但是,您可以通过在每个新行之前发出一个来模拟效果,例如:

i=5
tput clear
tput cup $i 15
ping google.com | 
while read; do 
  tput cup $((++i)) 15
  echo "$REPLY"
done

或者作为单个“命令”:

i=5; tput clear; tput cup $i 15; ping google.com | 
while read; do tput cup $((++i)) 15; echo "$REPLY"; done

根据光标操作的复杂程度,您可能希望在ncurses.另一种选择可能是Bash 简单的诅咒

相关内容