【问题标题】:Linux bash: strange behavior after getting terminal cursor positionLinux bash:获取终端光标位置后的奇怪行为
【发布时间】:2020-05-27 01:18:45
【问题描述】:

我编写了一个 shell 脚本来在成功登录后收集并显示一些信息。 但是,有些信息需要一些时间来收集,所以我在一些标题和已经可用的信息之前打印到终端(ssh putty),然后再返回并将延迟的信息打印到正确的位置。

为了实现这一点,我使用以下脚本来获取当前光标位置,(忽略之前出现的所有无聊的东西。这是一堆 printf、cat 和 cut...

. ...
. ...
printf "^[[0m""\n"

# Get current settings.
if ! termios="$(stty -g 2>/dev/null)" ; then
    echo "Not running in a terminal." >&2
    exit 1
fi

# Restore terminal settings when the script exits.
trap "stty '$termios'" EXIT

# Disable ICANON ECHO. Should probably also disable CREAD.
stty -icanon -echo

# Request cursor coordinates
printf '\033[6n'

# Read response from standard input; note, it ends at R, not at newline
read -d "R" rowscols

# Clean up the rowscols (from \033[rows;cols -- the R at end was eaten)
rowscols="${rowscols//[^0-9;]/}"
rowscols=("${rowscols//;/ }")
#printf '(row %d, column %d)\n' ${rowscols[0]} ${rowscols[1]}    *<-- commented by me*

# Reset original terminal settings.
stty "$termios"

# To the stuff...
printf '(row %d, column %d)\n' ${rowscols[0]} ${rowscols[1]}

line=${rowscols[0]}
line=$(($line - 10))                        *<--- Indeed script's line 102. I want subtract 10*
col=56
printf '(r= %d, c= %d)\n' ${line} ${col}    *<--- Printed two times, both times wrong values*

exit 1      *<--- Put here just to exit earlier*


## Get uptime/activetime formated to my taste.
m_activetime=$(/usr/bin/activetime -v)
printf "\33[%d;%dH^[[38;5;196m ${m_activetime}" ${line} ${col}
. ...
. ...

当我运行代码时,我得到:

. ...
. ...
. ...
    ||=-= _ |-=-   |+++++++| _    ||= _   |            :
`~‾‾ '--~~__|- =   |+++++__|----~‾  ‾~`---',  CPU stat⸱:
             ~---__|,--~'                     Weather⸱⸱:

(row 16, column 1)
./c.asc: line 102: 16 1 - 10: syntax error in expression (error token is "1 - 10")
(r= 16, c= 1)
(r= 56, c= 0)
lr@pi:~ $

1) 脚本是 bash (shebang #!/usr/bash)

2) (row 16, column 1) 行似乎没问题!

3) 脚本名为 c.asc

4) 我想知道这个错误到底是什么,我以前用过类似的表达式,不是用 bash 数组,但即便如此......

line 102: 16 1 - 10: syntax error 我可以猜到 16,但是 1 - 10 是从哪里来的?

(error token is "1 - 10") 什么令牌“1 - 10”????!!!

5) 第一个(r= 16, c= 1)已经错了,应该是(r= 6, c= 56)。为什么是这样? 10的减法是怎么回事?变量 col 的值去哪了?

6) 更奇怪。我没有指示第二次打印,即便如此,现在变量 line 存在身份危机并显示 col 值,并且在这两种情况下指令 col= 56 似乎被忽略了。变量line为什么以及如何得到变量col的值?为什么变量 col 会从错误的值 1 变为错误的值 0?

7) 显示的脚本已被转换以跟踪错误。它首先没有打印到预期的位置,并显示错误。还有一个版本的 printf printf '(r= %d, c= %d)\n' $((${line} - 10)) ${col} 显示同样相似和离奇的错误。


附言

经过一些额外的实验,只使用脚本的一部分来获取终端光标位置,它似乎也不完全正常。它可以返回位置,但尝试像 read r c &lt; &lt;(curspos) 之类的东西(假设 curspos 是返回元组 lin col 的脚本的名称),提示会挂起,直到按下 Ctrl-C 之后这个提示太疯狂了。

谢谢

【问题讨论】:

    标签: linux bash terminal text-cursor


    【解决方案1】:

    问题是您将值引用到数组中。

    rowscols=("${rowscols//;/ }")
    

    这告诉 bash 忽略空格并将其视为一个值。所以当你稍后用${rowscols[0]} 得到第一个值时,你实际上得到的是16 1 而不是16 并且没有第二个值。

    它也适用于这个 printf,因为你没有引用那里的值。

    printf '(row %d, column %d)\n' ${rowscols[0]} ${rowscols[1]}
    

    我不知道为什么最后一次 printf 运行了两次,但似乎可以通过引用解决。

    【讨论】:

    • 先生。 pynexj 解决方案(下)有效。没有重复打印,并且为行和列计算的值是正确的。所以 James R. 先生是正确的,“引用的值”会导致重大的不可预测的问题。我从互联网上获取了光标位置的代码,无论我对 stty 文档进行了多少研究,我都不理解它的特定 sn-p。但是,该代码不能用作可调用脚本,我不能使用read l c &lt; &lt;(./cpr.sh)lc=$(./cpr.sh),shell 挂起,在 Ctrl-C 之后我得到“stty:'标准输入':输入/输出错误”,充其量,或者最糟糕的是之后没有任何效果。
    猜你喜欢
    • 2012-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    相关资源
    最近更新 更多