2010-04-04 9 views
20

Bir bash komut dosyasında, imleç sütununu bir değişkende almak istiyorum. Bu örneğin, bunu elde etmek için tek yoldur aşağıdaki şekilde ANSI çıkış kodu {ESC}[6n kullanarak benzer:Bash içinde imleç konumu nasıl alınır?

# 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 

Maalesef bu standart çıkışa karakterleri yazdırır ve ben sessizce yapmak istiyorum. Ayrıca, bu çok taşınabilir değil ...

Bunu başarmak için saf bir yol var mı?

cevap

29

Sen kirli hileler başvurmak zorunda: Ben bilmesi çözülebilir biliyorum

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

Vay, terminali değiştirmeyi düşünmedim, teşekkürler! – nicoulaj

+0

Bu "bash" kodunu "C" dilinde nasıl kullanabiliriz? – Rasoul

+1

@Rasoul: Bunu ayrı bir soru olarak sormalısınız. –

8

, ama sadece "-s" ile sessizce çalışmaya okumak söyler misiniz:

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

Ve sonra CURPOS, "21; 3" gibi bir şeye eşittir. taşınabilirlik çıkarları

+1

Benim için bu interaktif bir kabukta çalışır ancak bir betik içinde değil – etuardu

+0

Bunun için, bir Makefile satırının geri kalanını doldurmak zorunda kaldım ve bunun içinde bir işlevle bitti: echo "\ 033 [6n \ c" ; -sdR CURPOS okuyun; COLS_LEFT = "$$ (expr $$ TERM_COLS - $$ (echo $$ {CURPOS} | cut -d ';' -f 2;) + 1)"; – mVChr

+0

'echo -en" \ 033 [6n "; 1 uyku; read -sdR' Bu yöntem yanlış. Echo'yu echo komutundan önce devre dışı bırakmanız gerekir. – zhangyoufu

2

ben kaç gibi kabuklarda çalışacak bir vanilya POSIX uyumlu bir sürümünü kılmayı gitmek yaşadım:

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

... ama bulmak gibi olamaz bash'ın 'read -d' için uygun bir alternatif. Uyku olmadan, komut döndürme çıktısını tamamen kaybeder ...

-6

Tput komutları, kullanmanız gereken şeydir. Ekrana basit, hızlı, çıkış yok.

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

Bunun için hangi işletim sistemini ve sürümü kullanıyorsunuz? Sistemimde, "col" ve "line" olarak adlandırılan terminfo özellikleri yoktur. Bununla birlikte, çoğullar, "cols" ve "lines" ler vardır, fakat mevcut imleç pozisyonundan ziyade toplam sütun ve satır sayısını döndürürler. –