2010-04-04 30 views
20

En un script bash, quiero poner la columna del cursor en una variable. Parece que utilizando el código de escape ANSI {ESC}[6n es la única manera de conseguirlo, por ejemplo, de la siguiente manera:¿Cómo obtener la posición del cursor en bash?

# 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 

Desafortunadamente, esto imprime caracteres en la salida estándar y quiero hacerlo en silencio. Además, esto no es muy portátil ...

¿Hay una manera pura de bash para lograr esto?

Respuesta

29

Hay que recurrir a trucos sucios:

#!/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)) 
+0

¡Guau, no pensé en cambiar de terminal, gracias! – nicoulaj

+0

¿cómo podemos usar este código 'bash' en el lenguaje' C'? – Rasoul

+1

@Rasoul: Deberías preguntar eso como una pregunta separada. –

8

Sé que puede ser resuelto por saber, pero que acaba de leer podría decir que trabajar en silencio con "s":

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

Y luego CURPOS es igual a algo así como "21; 3".

+1

Para mí esto funciona en el shell interactivo pero no dentro de un script – etuardu

+0

Gracias por esto, tuve que completar el resto de la línea en un Makefile y terminé con esto dentro de una función: 'echo" \ 033 [6n \ c " ; leer -sdR CURPOS; COLS_LEFT = "$$ (expr $$ TERM_COLS - $$ (echo $$ {CURPOS} | cut -d ';' -f 2;) + 1)"; ' – mVChr

+0

' echo -en "\ 033 [6n"; dormir 1; leer -sdR' Este método es incorrecto. Debe desactivar lflag ECHO antes del comando echo. – zhangyoufu

2

En aras de la portabilidad que he tenido un ir a hacer una versión compatible con POSIX de vainilla que se ejecutará en el tablero como conchas:

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

... pero me parece que no puede encontrar una alternativa viable para 'de bash leer -d'. Sin la suspensión, la secuencia de comandos omite por completo la salida de retorno ...

-6

Los comandos tput son los que necesita usar. simple, rápido, sin salida a la pantalla.

#!/bin/bash 
col=`tput col`; 
line=`tput line`; 
+10

¿Qué sistema operativo y versión está usando que esto funcione para usted? En mi sistema, no hay capacidades terminfo llamadas "col" y "line". Sin embargo, existen los plurales, "cols" y "lines", pero devuelven el número total de columnas y líneas en lugar de la posición actual del cursor. –

Cuestiones relacionadas