Dikey imleç konumunu al


10

Bu oldukça garip gelebilir, ancak Bash'te dikey imleç konumunu nasıl ayarlayacağımı biliyorum:

echo -e "\e[12H"

Bu, imleci 12. satıra taşır (1 ile başlayan).

Peki linux bash kullanarak imleç konumunu (satır numarası) nasıl alabilirim? Bu değeri bir değişkente saklayabilseydim, onunla hesaplayabilmem yararlı olurdu.

DÜZENLE:

Aldığım hata bu:

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

Ayrıca bkz. Örnek bir komut dosyası (ek kısıtlamaları olduğu için en basit değil).
Gilles 'SO- kötü olmayı kes

Yanıtlar:


6

SO başlıklı aynı makalede yer alan bazı örnekleri kullanabildim: Bash içinde imleç konumu nasıl elde edilir? . Bunu sadece çalıştıklarını ve çözüm içeriğinin aslında U&L'de olduğunu göstermek için gönderiyorum.

Bash çözümleri

Bir komut dosyasının içinden

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

NOT: Çıktıyı biraz değiştirdim!

Misal

$ ./rowcol.bash 
(row,col): 43,0
$ clear
$ ./rowcol.bash 
(row,col): 1,0

Etkileşimli kabuk

Bu komut zinciri, imlecin satır ve sütun konumlarını almak için çalıştı:

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

Misal

$ 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

Not: Bu yöntem, herhangi bir komut dosyası türünden kullanılabilir görünmüyor. Etkileşimli bir terminaldeki basit komutlar bile benim için işe yaramadı. Örneğin:

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

süresiz olarak takılıyor.

tire / sh çözümleri

Bir komut dosyasının içinden

Bu çözüm dash, POSIX uyumlu olan stokla gelen Ubuntu / Debian sistemleri içindir . Bu nedenle, readkomut -ddiğer farklılıklar arasında geçişi desteklemez .

Bunun üstesinden gelmek sleep 1için -danahtarın yerine kullanılan bu çözüm vardır . Bu ideal değildir ancak en azından çalışan bir çözüm sunar.

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

Misal

$ ./rowcol.sh 
(row,col): 0,24
$ clear
$ ./rowcol.sh 
(row,col): 0,1

Etkileşimli kabuk

Sadece shinteraktif bir kabukta işe yarayan uygulanabilir bir çözüm bulamadım .


Bu sadece bash ile çalışıyor gibi görünüyor. Ve sh ile değil. Şahsen sh'i tercih ederim. Peki bunu sh ile nasıl kullanabilirim?
BrainStone

1
@BrainStone - bir yol bulamadığımdan araştırma yapmama izin ver.
slm

sh rowcol.sh. İlk satıra ( #!/bin/bashveya #!/bin/sh) ne koyduğunuz ya da dosyanın bittiği önemli değil!
BrainStone

@BrainStone - ama bence shsadece bir uyumluluk modu bash. Bunu yaptığımda ( sh rowcol.bash) işe yarıyor, o zaman sizin için çalışmıyor mu?
slm

1
@BrainStone - bir takma ad yapabilir misiniz alias sh=bash?
slm

17

Bulmak -pyerine seçeneği kullanarak echobir komut dosyası asılı sorunu çözüldü. İle test edildi GNU bash, version 3.00.16(1)-release (x86_64-redhat-linux-gnu).

IFS=';' read -sdR -p $'\E[6n' ROW COL;echo "${ROW#*[}"

etkileşimli olarak veya bir komut dosyasında çalışır:

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

Çıktılar:

, $. / Cursor.sh
3.00.16 (1) -salınımı
6; 11 6 11
26; 16 26 16

Bu çok iyi çalışıyor. Ne yazık ki, arka plan işlemlerinde çalışmaz ve ekran ilerledikçe kaydedilen sütunun altındaki çizgi değişir.
leondepeon

4

İmleç konumunu ANSI CSI DSR(Aygıt Durum Raporu): ile alabilirsiniz \e[6n. Sorgunuzda belirttiğiniz ANSI CSR CUP(İmleç Konumu) benzeri bir biçimde döndürdüğünü , ancak formu izlediğini unutmayın \e[n;mR(burada n satırdır ve m sütundur).

Vikipedi'de ANSI kaçış kodlarının ayrıntıları .

Değeri bir değişkene almak için, bu StackOverflow üzerinde cevaplandı .

Önceki bir yanıt / yorumda belirtildiği gibi (ve wikipedia makalesinde ayrıntılı olarak belirtildiği gibi), bu kodlar her zaman taşınabilir değildir (terminalden terminale ve işletim sisteminden işletim sistemine). Hala bunun termcap / curses ile daha iyi ele alındığını düşünüyorum;)


Ve bunu bir değişkende nasıl saklayabilirim?
BrainStone

Çalıştıramıyorum. Hep birlikte sorunları olsun echo -e, echo -enve read .... Bu sadece kod dosyada mevcut olduğunda olur! Bunu gerçekten anlamıyorum!
BrainStone

Görünüşe göre bazı ayarları bozdum. echo -edaha önce çalıştı ama şimdi değil! Buna ne sebep olmuş olabilir ve nasıl geri yüklerim?
BrainStone

2

POSIX shsözdizimi ile:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.