수직 커서 위치 가져오기

수직 커서 위치 가져오기

이상하게 들릴 수도 있지만 Bash에서 수직 커서 위치를 다음과 같이 설정하는 방법을 알고 있습니다.

echo -e "\e[12H"

그러면 커서가 12번째 줄(1부터 시작)으로 이동합니다.

그렇다면 Linux bash를 사용하여 커서 위치(줄 번호)를 얻는 방법은 무엇입니까? 이 값을 변수에 저장하여 계산을 수행할 수 있다면 도움이 될 것입니다.

편집하다:

내가 얻는 오류는 다음과 같습니다.

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

답변1

-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

답변2

나는 다음과 같은 제목의 동일한 기사에서 몇 가지 예를 사용할 수 있었습니다.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대화형 쉘에서만 작동하는 작동 솔루션을 찾을 수 없습니다 .

답변3

ANSI CSI DSR(장치 상태 보고서)를 통해 커서 위치를 얻을 수 있습니다 \e[6n. 질문(커서 위치)에서 언급한 것과 유사한 형식으로 반환되지만 ANSI CSR CUP형식 \e[n;mR(n은 행이고 m은 열)을 따릅니다.

ANSI 이스케이프 코드에 대한 자세한 내용은 다음을 참조하세요.위키피디아.

값을 변수에 저장하기 위해 이것은 답변되었습니다.스택 오버플로.

에서 언급했듯이이전 답변/댓글(자세한 내용은 Wikipedia 기사 참조) 이러한 코드는 항상 이식 가능한 것은 아닙니다(터미널에서 터미널로, 운영 체제에서 운영 체제로). 나는 아직도 이것이 termcap/curses를 사용하여 더 잘 처리된다고 생각합니다;)

답변4

POSIX sh구문을 사용하십시오.

if [ -t 0 ] && [ -t 1 ]; then
  old_settings=$(stty -g) || exit
  trap 'stty "$(old_settings)"' INT TERM QUIT ALRM
  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"
  trap - INT TERM QUIT ALRM
fi

관련 정보