获取垂直光标位置


10

这听起来可能很奇怪,但是我知道如何像这样在Bash中设置垂直光标位置:

echo -e "\e[12H"

这会将光标移动到第12行(从1开始)。

那么如何使用linux bash获取光标位置(行号)呢?如果我可以简单地将此值存储在变量中,以便可以进行计算,则将很有帮助。

编辑:

这是我得到的错误:

$ sh rowcol.sh
-en
    read: 9: Illegal option -d
                              test.sh: 12: Bad substitution

另请参见示例脚本(不是最简单的脚本,因为该脚本具有其他约束)。
吉尔(Gilles)'所以

Answers:


5

我能够使用同一篇关于SO的文章中的一些示例,标题为:如何获取bash中的光标位置?。我将其发布在此处只是为了表明它们有效,并且解决方案的内容实际上也包含在U&L中。

重击解决方案

从脚本内部

#!/bin/bash
# based on a script from http://invisible-island.net/xterm/xterm.faq.html
exec < /dev/tty
oldstty=$(stty -g)
stty raw -echo min 0
# on my system, the following line can be replaced by the line below it
echo -en "\033[6n" > /dev/tty
# tput u7 > /dev/tty    # when TERM=xterm (and relatives)
IFS=';' read -r -d R -a pos
stty $oldstty
# change from one-based to zero based so they work with: tput cup $row $col
row=$((${pos[0]:2} - 1))    # strip off the esc-[
col=$((${pos[1]} - 1))

echo "(row,col): $row,$col"

注意:我稍微改变了输出!

$ ./rowcol.bash 
(row,col): 43,0
$ clear
$ ./rowcol.bash 
(row,col): 1,0

互动壳

该命令链用于获取游标的行和列位置:

$ echo -en "\E[6n";read -sdR CURPOS; CURPOS=${CURPOS#*[};echo "${CURPOS}"

$ echo -en "\E[6n";read -sdR CURPOS; CURPOS=${CURPOS#*[};echo "${CURPOS}"
13;1
$ clear
$ echo -en "\E[6n";read -sdR CURPOS; CURPOS=${CURPOS#*[};echo "${CURPOS}"
2;1

注意:此方法似乎无法在任何类型的脚本中使用。即使是交互式终端中的简单命令对我也不起作用。例如:

$ pos=$(echo -en "\E[6n";read -sdR CURPOS; CURPOS=${CURPOS#*[};echo "${CURPOS}")

无限期地挂起。

破折号/ sh解决方案

从脚本内部

该解决方案适用于随附dashPOSIX的Ubuntu / Debian系统。因此,该read命令不支持-d其他差异之间的切换。

为了解决这个问题,可以使用此解决方案sleep 1代替-d开关。这不是理想的方法,但至少提供了可行的解决方案。

#!/bin/sh

exec < /dev/tty
oldstty=$(stty -g)
stty raw -echo min 0
tput u7 > /dev/tty
sleep 1
IFS=';' read -r row col
stty $oldstty

row=$(expr $(expr substr $row 3 99) - 1)        # Strip leading escape off
col=$(expr ${col%R} - 1)                        # Strip trailing 'R' off

echo "(row,col): $col,$row"

$ ./rowcol.sh 
(row,col): 0,24
$ clear
$ ./rowcol.sh 
(row,col): 0,1

互动壳

我找不到仅适用sh于交互式外壳的可行解决方案。


这似乎仅适用于bash。而不是与sh。我个人更喜欢sh。那我怎么用sh呢?
BrainStone 2013年

1
@BrainStone-让我研究一下,看看我是否找不到方法。
slm

sh rowcol.sh。放在第一行(#!/bin/bash#!/bin/sh)或文件的末尾都无所谓!
BrainStone

@BrainStone-但我认为sh仅仅是的兼容模式bash。当我这样做(sh rowcol.bash)时,它对您不起作用吗?
slm

1
@BrainStone-您可以创建一个别名alias sh=bash
slm

17

使用-p选项而不是echo我发现解决了脚本中的挂起问题。经过测试GNU bash, version 3.00.16(1)-release (x86_64-redhat-linux-gnu)

IFS=';' read -sdR -p $'\E[6n' ROW COL;echo "${ROW#*[}"

交互工作或在脚本中工作:

#!/usr/bin/env bash
function pos
{
    local CURPOS
    read -sdR -p $'\E[6n' CURPOS
    CURPOS=${CURPOS#*[} # Strip decoration characters <ESC>[
    echo "${CURPOS}"    # Return position in "row;col" format
}
function row
{
    local COL
    local ROW
    IFS=';' read -sdR -p $'\E[6n' ROW COL
    echo "${ROW#*[}"
}
function col
{
    local COL
    local ROW
    IFS=';' read -sdR -p $'\E[6n' ROW COL
    echo "${COL}"
}
tput sc         # Save cursor position
tput cup 5 10   # Move to row 6 col 11
POS1=$(pos)     # Get the cursor position
ROW1=$(row)
COL1=$(col)
tput cup 25 15  # Move to row 25 col 15
POS2=$(pos)     # Get the cursor position
ROW2=$(row)
COL2=$(col)
tput rc # Restore cursor position
echo $BASH_VERSION
echo $POS1 $ROW1 $COL1
echo $POS2 $ROW2 $COL2

输出:

$。/ cursor.sh
3.00.16(1)-发布
6; 11 6 11
26; 16 26 16

这很好。但是,令人遗憾的是,它在后台进程中不起作用,并且随着屏幕滚动,已保存列下的行会更改。
leondepeon '18

4

您可以通过ANSI CSI DSR(设备状态报告)获取光标位置:\e[6n。请注意,它以类似于ANSI CSR CUP您在问题中提到的(光标位置)的格式返回它,但是它遵循以下形式\e[n;mR(其中n是行,m是列)。

维基百科上有关ANSI转义码的更多详细信息。

为了将值保存到变量中,在StackOverflow上进行了回答。

先前的答案/评论中所述(并在Wikipedia文章中进行了详细介绍),这些代码并不总是可移植的(从终端到终端以及从OS到OS)。我仍然认为这可以用termcap / curses更好地处理;)


我如何将其存储在变量中?
BrainStone

我无法正常工作。我经常遇到问题echo -eecho -en并且read ...。仅当文件中存在代码时才会发生这种情况!我真的不太明白!
BrainStone

好像我打破了某些设置。echo -e曾经工作过,但现在没有了!可能是什么原因造成的,如何恢复?
BrainStone 2013年

2

使用POSIX sh语法:

if [ -t 0 ] && [ -t 1 ]; then
  old_settings=$(stty -g) || exit
  stty -icanon -echo min 0 time 3 || exit
  printf '\033[6n'
  pos=$(dd count=1 2> /dev/null)
  pos=${pos%R*}
  pos=${pos##*\[}
  x=${pos##*;} y=${pos%%;*}
  stty "$old_settings"
fi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.