垂直カーソル位置を取得する


10

これは奇妙に聞こえるかもしれませんが、次のようにBashで垂直カーソル位置を設定する方法を知っています。

echo -e "\e[12H"

これにより、カーソルが(1から始まる)12行目に移動します。

では、Linux bashを使用してカーソル位置(行番号)を取得するにはどうすればよいですか?この値を変数に格納して、計算できるようにしておくと便利です。

編集:

これは私が得るエラーです:

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

サンプルスクリプトも参照してください(追加の制約があるため、最も単純ではありません)。
Gilles「SO-邪悪なことをやめる」

回答:


5

SOに関する同じ記事のタイトルのいくつかの例を使用できました:bashでカーソル位置を取得するにはどうすればよいですか?。私はこれをここに投稿していますが、それらが機能し、ソリューションのコンテンツが実際にU&Lにもあることを示しています。

Bashソリューション

スクリプトの中から

#!/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 2013

@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

4

ANSI CSI DSR(デバイスステータスレポート)を介してカーソル位置を取得できます\e[6nANSI CSR CUP質問で言及した(カーソル位置)と同様の形式で返されますが、形式は異なります\e[n;mR(nは行、mは列です)。

ウィキペディアの ANSIエスケープコードの詳細。

変数に値を保持するために、これはStackOverflowで回答されました。

以前の回答/コメント(およびWikipediaの記事で詳細)で述べたように、これらのコードは常に(端末から端末へ、OSからOSへ)移植可能であるとは限りません。これはまだtermcap / cursesで処理する方が良いと思います;)


そして、どうすればこれを変数に格納できますか?
BrainStone 2013

うまくいきません。私はいつもの問題を取得しecho -eecho -enそしてread ...。これは、コードがファイルに存在する場合にのみ発生します!よくわからない!
BrainStone 2013

設定を壊したようです。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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.