2010-04-04 49 views
20

Trong tập lệnh bash, tôi muốn lấy cột con trỏ trong một biến. Dường như sử dụng mã thoát ANSI {ESC}[6n là cách duy nhất để có được nó, ví dụ theo cách sau:Cách lấy vị trí con trỏ trong 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 

Thật không may, điều này in ký tự vào đầu ra tiêu chuẩn và tôi muốn làm điều đó âm thầm. Bên cạnh đó, điều này không phải là rất xách tay ...

Có cách nào để đạt được điều này không?

Trả lời

29

Bạn phải dùng thủ đoạn bẩn:

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

Ồ, tôi không nghĩ đến việc chuyển đổi thiết bị đầu cuối, cảm ơn bạn! – nicoulaj

+0

làm cách nào chúng ta có thể sử dụng mã 'bash' này trong ngôn ngữ' C'? – Rasoul

+1

@Rasoul: Bạn nên hỏi đó là một câu hỏi riêng. –

8

Tôi biết nó có thể được giải quyết bằng bí quyết, nhưng bạn chỉ có thể nói đọc để hoạt động âm thầm với "-s":

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

Và sau đó CURPOS là tương đương với một cái gì đó như "21; 3".

+1

Đối với tôi công trình này trong vỏ tương tác nhưng không phải bên trong một kịch bản – etuardu

+0

Cảm ơn điều này, tôi đã phải điền vào phần còn lại của dòng trong một Makefile và kết thúc với điều này bên trong một hàm: 'echo" \ 033 [6n \ c " ; đọc -sdR CURPOS; COLS_LEFT = "$$ (expr $$ TERM_COLS - $$ (echo $$ {CURPOS} | cắt -d ';' -f 2;) + 1)"; ' – mVChr

+0

' echo -en "\ 033 [6n"; ngủ 1; read -sdR' Phương pháp này không chính xác. Bạn phải tắt lflag ECHO trước lệnh echo. – zhangyoufu

2

Trong lợi ích của tính di động Tôi đã có một đi vào thực hiện một phiên bản POSIX tương thích vani mà sẽ chạy trong vỏ như dấu gạch ngang:

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

... nhưng tôi dường như không thể tìm thấy một thay thế khả thi cho bash 'đọc -d'. Nếu không có chế độ ngủ, tập lệnh sẽ xóa hoàn toàn kết quả trả về ...

-6

Lệnh tput là những gì bạn cần sử dụng. đơn giản, nhanh chóng, không có đầu ra cho màn hình.

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

Bạn đang sử dụng hệ điều hành và phiên bản nào mà nó hoạt động cho bạn? Trên hệ thống của tôi, không có khả năng terminfo được gọi là "col" và "line". Tuy nhiên, các số nhiều, "cols" và "dòng", tồn tại, nhưng chúng trả về tổng số cột và dòng chứ không phải là vị trí con trỏ hiện tại. –

Các vấn đề liên quan