35

bash スクリプトで、カーソル列を変数に取得したいと考えています。ANSIエスケープコードを使用する{ESC}[6nことがそれを取得する唯一の方法のようです。たとえば、次の方法です。

# Query the cursor position
echo -en '\033[6n'

# Read it to a variable
read -d R CURCOL

# Extract the column from the variable
CURCOL="${CURCOL##*;}"

# We have the column in the variable
echo $CURCOL

残念ながら、これは文字を標準出力に出力するので、静かに実行したいと思います。その上、これはあまり移植性がありません...

これを達成するための純粋なbashの方法はありますか?

4

7 に答える 7

42

あなたは汚いトリックに頼らなければなりません:

#!/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))
于 2010-04-04T18:57:07.797 に答える
14

フラグreadを使用してサイレントに作業するように指示できます。-s

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

そして、CURPOS は のようなものに等しくなります21;3

于 2011-05-14T16:02:03.737 に答える
3

移植性のために、dash のようなシェルで実行される標準の POSIX 互換バージョンを作成してみました。

#!/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 $col,$row

...しかし、bash の ' read -d 'の実行可能な代替手段が見つからないようです。スリープがないと、スクリプトは戻り出力を完全に見逃してしまいます...

于 2012-09-09T18:39:00.473 に答える
3

私の(2つの)バージョンの同じ...

関数として、ncurses のユーザー定義コマンドを使用して、特定の変数を設定します。

getCPos () { 
    local v=() t=$(stty -g)
    stty -echo
    tput u7
    IFS='[;' read -rd R -a v
    stty $t
    CPos=(${v[@]:1})
}

今より:

getCPos 
echo $CPos
21
echo ${CPos[1]}
1
echo ${CPos[@]}
21 1

declare -p CPos
declare -a CPos=([0]="48" [1]="1")

注:私はncursescommand: tput u7at 行を使用します。これは、 string by command:を使用するよりも移植性#4が高くなることを期待しています ... わかりません: とにかく、これはそれらのいずれでも機能します:VT220printf "\033[6n"

getCPos () { 
    local v=() t=$(stty -g)
    stty -echo
    printf "\033[6n"
    IFS='[;' read -ra v -d R
    stty $t
    CPos=(${v[@]:1})
}

VT220互換の TERMの下では、まったく同じように動作します。

より詳しい情報

そこにいくつかのドキュメントが見つかるかもしれません:

VT220 プログラマ リファレンス マニュアル - 第 4 章

4.17.2 デバイス ステータス レポート (DSR)

...

Host to VT220 (Req 4 cur pos)  CSI 6 n       "Please report your cursor position using a CPR (not DSR) control sequence."
  
VT220 to host (CPR response)   CSI Pv; Ph R  "My cursor is positioned at _____ (Pv); _____ (Ph)."
                                              Pv =  vertical position (row)
                                              Ph =  horizontal position (column)
于 2018-08-20T11:57:46.560 に答える
-10

tput コマンドは、使用する必要があるものです。シンプル、高速、画面への出力なし。

#!/bin/bash
col=`tput col`;
line=`tput line`;
于 2012-11-11T07:38:20.453 に答える