2010-04-04 12 views
20

Dans un script bash, je veux obtenir la colonne du curseur dans une variable. Il ressemble à l'aide du code d'échappement ANSI {ESC}[6n est la seule façon de l'obtenir, par exemple de la manière suivante:Comment obtenir la position du curseur dans 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 

Malheureusement, cela imprime des caractères à la sortie standard et je veux le faire en silence. En outre, ce n'est pas très portable ...

Existe-t-il un moyen pur-bash pour y parvenir?

Répondre

29

Vous devez recourir à des trucs sales:

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

Wow, je n'ai pas pensé à changer de terminal, merci! – nicoulaj

+0

comment pouvons-nous utiliser ce code 'bash' dans le langage' C'? – Rasoul

+1

@Rasoul: Vous devriez poser cette question séparément. –

8

Je sais qu'il peut être résolu par le savoir, mais vous pourriez simplement lire travailler en silence avec « -s »:

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

Et puis CURPOS est égal à quelque chose comme "21; 3".

+1

Pour moi, cela fonctionne dans le shell interactif mais pas dans un script – etuardu

+0

Merci pour cela, j'ai dû remplir le reste de la ligne dans un Makefile et fini avec ceci dans une fonction: 'echo" \ 033 [6n \ c " ; lire -sdR CURPOS; COLS_LEFT = "$$ (expr $$ TERM_COLS - $$ (echo $$ {CURPOS} | coupe -d ';' -f 2;) + 1)"; ' – mVChr

+0

' echo -en "\ 033 [6n"; dormir 1; read -sdR' Cette méthode est incorrecte. Vous devez désactiver lflag ECHO avant la commande echo. – zhangyoufu

2

Dans l'intérêt de la portabilité que j'ai eu un aller à faire une version compatible POSIX vanille qui se déroulera dans des coquilles comme tableau de bord:

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

... mais je ne peux pas sembler trouver un alternative viable pour bash 'lu -d'. Sans le mode veille, le script manque complètement la sortie de retour ...

-6

Les commandes de tput sont ce que vous devez utiliser. simple, rapide, pas de sortie à l'écran.

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

Quel OS et quelle version utilisez-vous pour que cela fonctionne pour vous? Sur mon système, il n'y a pas de capacités terminfo appelées "col" et "ligne". Cependant, les pluriels, "cols" et "lines" existent, mais ils renvoient le nombre total de colonnes et de lignes plutôt que la position actuelle du curseur. –

Questions connexes