Net yaparken metnin / ekranın yanıp sönmesini önleyin


11

Benim senaryom gibi bir şey yapıyor:

while :;
   clear

   do_a_lot_of_output_here

   sleep 1
done

Net ve çıktı yaparken ekranın yanıp sönmesini önlemek için herhangi bir seçenek var mı? Bunu watchkomutta olduğu gibi yapmak istiyorum (ama yazıldığı gibi C). Önerileriniz var mı?

clear | hexdump -C

00000000  1b 5b 48 1b 5b 32 4a                              |.[H.[2J|
00000007

PS. Sadece kullanıyorum bash.


Çıktılarınızı ekleyebilir misiniz clear | hexdump -C?
ott--

Soruyu genişletiyorum.
ravnur

Stackoverflow.com/questions/5367068/… üzerinde başka bir çözüm buldum - echo -en "\ec"flaş da mı?
ott--

Ben de buldum. Cevaptan her iki değişken de yanıp söner.
ravnur

: Bu aracı kullanarak başarılı olmuş excess.org/article/2009/07/watch1-bash-unicode
Raine

Yanıtlar:


8

Yanıp sönen komut dosyası tüm ekranı temizlediğinden oluşur. Mevcut metni boyar ve yalnızca gerektiği gibi temizlenirse, titreme olmaz.

İşte bir örnek:

#!/bin/sh
watchit() {
    HOME=$(tput cup 0 0)
    ED=$(tput ed)
    EL=$(tput el)
    ROWS=$(tput lines)
    COLS=$(tput cols)
    printf '%s%s' "$HOME" "$ED"
    while true
    do
        CMD="$@"
        ${SHELL:=sh} -c "$CMD" | head -n $ROWS | while IFS= read LINE; do
            printf '%-*.*s%s\n' $COLS $COLS "$LINE" "$EL"
        done
        printf '%s%s' "$ED" "$HOME"
        sleep 1
    done
}

watchit top -b -n 1

Bunu yapar:

  • çıktıyı ekrana sığacak şekilde verilen komuttan yazdırır (sarma veya kaydırma yok)
  • mevcut satırların üzerine yazar, her satırın üzerine yazılmayan kısmını temizler
  • edterminalinizin geçerli konumdan ekranın sonuna kadar yazdırma yeteneğini kullanır .

Yeniden boyutlandırılabilir bir ekranı işlemek istiyorsanız, atamaları dış döngünün içine ROWSve COLSiçine taşıyabilirsiniz , ör.

#!/bin/sh
watchit() {
    HOME=$(tput cup 0 0)
    ED=$(tput ed)
    EL=$(tput el)
    printf '%s%s' "$HOME" "$ED"
    while true
    do
        ROWS=$(tput lines)
        COLS=$(tput cols)
        CMD="$@"
        ${SHELL:=sh} -c "$CMD" | head -n $ROWS | while IFS= read LINE; do
            printf '%-*.*s%s\n' $COLS $COLS "$LINE" "$EL"
        done
        printf '%s%s' "$ED" "$HOME"
        sleep 1
    done
}

watchit top -b -n 1

çünkü tputmevcut ekran boyutunu sistemden ister.

Daha fazla okuma:


1
Bazı işlevlere sahip küçük bir bağımsız komut dosyasına gömülü kullanmak #!/bin/bashve kullanmak isteyenler için watchityapabilirsiniz export -f function_name; watchit function_name.
aggregate1166877

Bu benim için mükemmel çalıştı, ancak ekranın üst kısmında, şeylerin daha uzun metin parçaları (kısaltılmış herhangi bir şey head) için değişeceği ve glitchy olacağı komik sorunlarla karşılaştım . Sorun, satır sayısını hesaplarken tek tek bir hata (en azından benim kurulumumda - bölme bölmelerinde ssh oturumu, iTerm2) gibi görünüyor. ROWS=`expr $(tput lines) - 1`bunu mükemmel bir şekilde ele aldı.
ohruunuruus

Bu harika, çok teşekkür ederim @ thomas-dickey.
mbarkhau

9

Yanıp sönmeyi önlemeye yardımcı olmanın bir yolu, ekranı temizlemeden önce tüm çıkışı almaktır, böylece temizleme ve yeniden çizme arasında minimum zaman kalır. Bu, çift tamponlama kavramına benzer:

while :; do
   output=$(do_a_lot_of_output_here)
   clear
   echo "$output"
   sleep 1
done

Bu titremeyi tamamen ortadan kaldırmaz, ancak deneyimimde çok daha az sıklıkta gerçekleşir.


Çift tamponlama, diğer tüm durumlarda olduğu gibi, günü
güvende tutar

Bir cazibe gibi çalıştı. Hiç titreme yok :)
Lars Juel Jensen

1
Kalan titreme clear, tampon içine dahil edilerek , yani ortadan kaldırılabilir output=$(clear; do_a_lot_of_output_here).
kdb

@kdb Güzel öneri! Bu benim için titremeyi neredeyse tamamen ortadan kaldırır ve kabul edilen cevaptan çok daha basittir.
Michael Mior

Bu bir cazibe gibi çalışıyor! İlk başta 'echo "$ output" daki çift tırnak işaretlerini kaçırdım ve sonra çizgiler karıştı. (Tüm beyaz alanlar tek boşluk olarak kabul edilir.)
Popup

5

Yanıp sönme, döngü etrafında her seferinde ekranı temizlemenin kaçınılmaz bir sonucudur. İmleci ekranın üstüne taşıyabilir ve bunun yerine eski çıktınızın bölümlerinin üzerine yazabilirsiniz.

# You may want to do this if your code is in a script.
unhide_cursor() {
    printf '\e[?25h'
}
trap unhide_cursor EXIT

# Hide the cursor (there is probably a much better way to do this)
printf '\e[?25l'
clear 
while true ; do
    # Move the cursor to the top of the screen but don't clear the screen
    printf '\033[;H' 
    do_a_lot_of_output_here
    sleep 1
done

Çıktınız küçülürse bu komut dosyası yapay nesneler bırakacaktır. Taşınabilir olması da pek olası değildir. Ben sadece urxvt, xterm ve st ile test ettim.


Bu durumda imleç, rastgele konumdan (ve tabii ki eserler) çıktının sonuna atlamaya başlar. Ayrıca tput clearaynı sonuçları denedim (yanıp sönen)
ravnur

İmleci gizlemek için senaryoya birkaç satır ekledim.

İmleç yok - atlama yok. Ama eserler hakkında? Çıktıda rastgele miktarda satır var. Yeni çıktıya başlamadan önce tüm komut dosyalarını boşluklarla doldurmam gerekir mi? Ama yine de, zamanınız ve çabalarınız için teşekkürler: benden +1 + ama
sorunumu

Bütün eserler kurtulmak için tek yol buldu: tput ed. Ama yanıp sönmesine neden oluyor
Ravnur

Hangi terminal emülatörünü kullanıyorsunuz? İle tput edhemen önce do_a_lot...hat, ben urxvt ancak xterm'den veya st yanıp görüyorum.

1

Cristian'in cevabının bir uzantısı olarak, konsol penceresi komutun çıktısından daha küçükse çalışan aşağıdaki bash işlevini yaptım:

function watcher()
{
    lines=$(tput lines)
    while true; do
        output="$($@ | head -n $lines)"
        clear
        echo -e "$output"
        sleep 2
    done
}

Bu, herhangi bir komutu saatçiye iletmenizi sağlar. Git kullanıyorsanız git config --global color.status alwaysve tuşlarını kullanın :

watcher git status

Her zaman güncellenen bir git durum çıkışı görüntüler.

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.