수직 커서 위치 가져 오기


10

이것은 이상하게 들릴지 모르지만 Bash에서 세로 커서 위치를 다음과 같이 설정하는 방법을 알고 있습니다.

echo -e "\e[12H"

커서가 12 번째 줄로 이동합니다 (1로 시작).

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

편집하다:

이것은 내가 얻는 오류입니다.

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

예제 스크립트 도 참조하십시오 (추가 제약 조건이 있으므로 가장 단순하지는 않습니다).
Gilles 'SO- 악마 그만'

답변:


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

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

4

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

Wikipedia 의 ANSI 이스케이프 코드에 대한 자세한 내용 .

변수에 값을 유지하기 위해 이것은 StackOverflow 에서 응답되었습니다 .

이전 답변 / 설명 에서 언급했듯이 (wikipedia 기사에 자세히 설명되어 있듯이 ) 이러한 코드는 항상 휴대 가능한 것은 아닙니다 (터미널에서 터미널 및 OS에서 OS로). 나는 여전히 이것이 termcap / curses로 더 잘 처리된다고 생각한다.)


그리고 이것을 변수에 어떻게 저장할 수 있습니까?
BrainStone

나는 그것을 작동시킬 수 없다. 난 항상 문제를 얻을 echo -e, echo -en그리고 read .... 파일에 코드가있는 경우에만 발생합니다! 나는 이것을 정말로 이해하지 못한다!
BrainStone

설정이 끊어진 것 같습니다. echo -e전에 일했지만 지금은 그렇지 않습니다! 이 문제의 원인은 무엇이며 어떻게 복원합니까?
BrainStone

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.