shell 测量终端输出后滚动了多少行

jaql4c8m  于 2023-02-24  发布在  Shell
关注(0)|答案(2)|浏览(162)

我正在编写一个bash脚本,它将内容显示到屏幕上,然后使用ANSI命令(或tput)移动光标并更新已经显示的内容。
我遇到的问题是,当输出开始向终端的下部移动时,输出可能会导致终端滚动-使所有绝对定位命令错过标记。
有没有一种方法可以测量我的输出导致终端滚动了多少行,这样我就可以修复我的光标地址?

cetgtptt

cetgtptt1#

不计算滚动行数......计算命令输出的行数可能会有好处吗?
例如,如果终端有20行(tput lines),命令输出40行,那么您知道“scroll”是20行(+/-取决于您如何计算后续的控制台/命令提示符)。

**注意:**目前我在(如果?)如何确定窗口中的当前行上画了一个空白(例如,在一个20行的窗口中,10行输出从第18行开始,所以滚动将是8);你能强制一个clear来确保输出总是从第一行开始吗(“在顶部”)?

根据Q&A: Count number of lines of output,一个想法是:

outcnt=$(command 2>&1 | tee /dev/stderr | wc -l)

试驾:

$ outcnt=$(printf "%s %s\n" {1..10} 2>&1 | tee /dev/stderr | wc -l) 
1 2
3 4
5 6
7 8
9 10

$ typeset -p outcnt
declare -- outcnt="5"

此特定示例还将在count中计算stderr:

$ outcnt=$(non-existent command 2>&1 | tee /dev/stderr | wc -l) 
-bash: non-existent: command not found

$ typeset -p outcnt
declare -- outcnt="1"

如果您不想计算stderr行数,请删除2>&1

$ outcnt=$(non-existent command | tee /dev/stderr | wc -l)
-bash: non-existent: command not found

$ typeset -p outcnt
declare -- outcnt="0"

计数stdout但不计数stderr的示例:

$ outcnt=$( { echo "hello"; non-existent command; } | tee /dev/stderr | wc -l)
-bash: non-existent: command not found
hello

$ typeset -p outcnt
declare -- outcnt="1"

这种方法的一种变体(特别是当您不能/不想使用outcnt=$(...)时)是让tee将输出的副本重定向到一个文件,然后使用wc -l重定向该文件。

ryhaxcpt

ryhaxcpt2#

由于滚动的问题,我现在已经放弃了使用绝对光标定位(甚至是"save_cursor "/" restore_cursor")。另一个我过去在类似的设置中实现过但在这里没有实现的选项是使用curses。
现在,我使用相对游标移动和计算输出的行数来计算要向上移动多少行才能到达输出的开头。
在文本溢出终端宽度的情况下,计算输出的行数可能有点挑战性,我使用以下代码来实现这一点:

local rows=0
for line in "${lines[@]}"; do
    local linewidth=$(tr -dc '[:print:]' <<<"$line" | wc -c)
    local outrows=$(( linewidth / $COLUMNS + $( [ $((linewidth % $COLUMNS)) -eq 0 ] && echo 0 || echo 1 ) ))
    rows=$(( rows + outrows ))
done
    • 注:**
  1. $COLUMNS是bash特定的全局变量,它包含终端的当前宽度-与从$(tput cols)获得的相同。
    1.使用trap code WINCH处理终端大小的更改留待将来练习...
    如果有更好的方法来处理滚动,我仍然希望看到一个更好的答案,我可以接受。

相关问题