पिछले आउटपुट को बैश में लिखने के बजाए उसे ओवरराइट कर दें


22

बैश टाइमर के लिए मैं इस कोड का उपयोग करता हूं:

#!/bin/bash
sek=60
echo "60 Seconds Wait!"
echo -n "One Moment please "
while [ $sek -ge 1 ]
do
   echo -n "$sek "  
sleep 1
   sek=$[$sek-1]
done
echo
echo "ready!"

जो मुझे ऐसा कुछ देता है

One Moment please: 60 59 58 57 56 55 ...

क्या सबसे हाल के द्वारा दूसरे के अंतिम मूल्य को बदलने की संभावना है ताकि आउटपुट एक बड़े निशान को उत्पन्न न करें लेकिन एक स्थिति में वास्तविक समय की तरह सेकंड उलटी गिनती? (आशा है कि आप समझते हैं कि मेरा क्या मतलब है :))


watchकमांड के साथ ऐसा करने का एक तरीका हो सकता है , हालांकि मुझे यकीन नहीं है कि यह कैसे करना है।
AJMansfield

जवाबों:


14
#!/bin/bash
sek=60
echo "60 Seconds Wait!"
echo -n "One Moment please "
while [ $sek -ge 1 ]
do
   echo -n "$sek" 

sleep 1
   sek=$[$sek-1]
   echo -en "\b\b"
done
echo
echo "ready!"

2
कमाल है, बहुत बहुत धन्यवाद। अन्य पाठकों के लिए सिर्फ एक सूचना। अंतरिक्ष के कारण आपको ऊपर दिए गए कोड को फिट करने के लिए echo -en "\ b \ b \ b" का उपयोग करना होगा।
एनईएस

1
+1 अच्छा, लेकिन ... 10 से नीचे यह संदेश खाना शुरू कर देता है ...
lep

1
हां, बेहतर उपयोग करने के लिए \r। मेरा जवाब देखिए।
मिकेल

3
बाश के मैनुअल से The old format $[expression] is deprecated and will be removed in upcoming versions of bash.:। इसके बजाय POSIX $((expression))या ((-command का उपयोग करें। उदाहरण के लिए sek=$(( sek - 1 ))या (( sek = sek - 1 ))या (( sek-- ))
जिरह

17

मूल रूप से अनीशेप के उत्तर के समान है, लेकिन \rबैकस्पेस ( \b) के बजाय रिटर्न ( ) का उपयोग करता है क्योंकि हम नहीं जानते कि क्या लंबाई हमेशा समान होगी, जैसे कि कब $sek < 10

इसके अलावा, आपके पहले echoका उपयोग करना चाहिए $sek, न कि हार्ड-कोड का 60

अंत में, के बाद अंतरिक्ष पर ध्यान दें ...

#!/bin/bash
sek=60
echo "$sek Seconds Wait!"
while [ $sek -ge 1 ]
do
   echo -ne "One Moment please $sek ... \r"
   sleep 1
   sek=$[$sek-1]
done
echo
echo "ready!"

7

बैश के साथ आप विशेष चर का उपयोग कर सकते हैं SECONDS

#BASH
SECONDS=0;
while sleep .5 && ((SECONDS <= 60)); do 
    printf '\r%s: %2d' "One moment please" "$((60-SECONDS))"
done
printf '\n'

+1 अच्छा जवाब, प्लस मैं SECONDS के बारे में कभी नहीं जानता था।
मिकेल

यह काम करता है, लेकिन यह 'स्लीप .5' देखने में थोड़ा अजीब है, जबकि एक परीक्षण के दौरान लूप की स्थिति है .. हावरर मुझे विशेष रूप से $ SECONDS का उपयोग पसंद है, क्योंकि यह वास्तविक समय से संबंधित है, (यानी बीच में एक निश्चित बीता हुआ समय नहीं है। समय लेने वाली क्रियाएं, जैसे कि नींद 1) ... SECONDS यह चर खोल शुरू होने के बाद से कुछ सेकंड तक फैलता है। (इसलिए मैं शायद इसे 0 पर सेट नहीं करूंगा। स्क्रिप्ट शुरू होने पर 60 सेकंड से अधिक समय तक इसका परीक्षण करें) .. +1
पीटर.ऑफ

मैं आगे टिप्पणी कर रहा हूं, केवल इसलिए कि मैं व्यक्तिगत रूप से एक सटीक कॉटनडाउन पाने के लिए इच्छुक हूं ... मैंने $ SECONDS का परीक्षण किया है और ऐसा लगता है कि यह '0' पर सेट है या नहीं यह अभी भी निर्भर है सिस्टम का वर्तमान आंशिक दूसरा .. यानी। इसे '0' पर सेट करने से 0.99 का समय निकल सकता है ... (जैसा कि इसे छोड़ दिया गया है, तो वही सच है) .... तो, इसका सबसे अच्छा औसत मौका केवल सेकंड के 5 के भीतर होना है। .. बस एक टिप्पणी (जो टिप्पणी के लिए कर रहे हैं :)
पीटर

@ fred.bear खैर, आप कभी भी इसे सही नहीं समझेंगे; कुछ अन्य प्रक्रिया CPU और / या IO को हग करना शुरू कर सकती है जबकि उलटी गिनती चल रही है और जो भी सटीकता आपके पास पहले थी उसे बर्बाद कर सकती है। आप जो कर सकते हैं, वह यह है कि कम से कम एक्स एमाउंट के लिए प्रतीक्षा करें , और यदि वांछित हो तो कुछ मोटे उलटफेर दें। जब एक कार्यक्रम कहता है "यह एक मिनट लगेगा", तो क्या आपको उम्मीद है कि यह बिल्कुल 1 मिनट, मिलीसेकंड तक ले जाएगा? या 1 मिनट लेने के लिए, कुछ सेकंड दें या लें?
जिरह

@geirha ... हाँ, यह भिन्नता ९९% मामलों में मायने नहीं रखेगी, और इसके महान आप ने मुझे $ SECONDS के बारे में अवगत कराया है ... मैं बस इसकी सीमाएँ ढूँढ रहा हूँ ... मैंने एक के साथ खेला है आपकी स्क्रिप्ट की भिन्नता जो .01 सेकंड की नींद के आधार पर परिष्करण समय की रिपोर्ट करती है (प्लस, जैसा कि आपने उल्लेख किया है, किसी भी बाहरी सिस्टम लैग) अभी तक केवल मुद्रण जब एक दूसरा क्लिक करता है, लेकिन तब मुझे पता चला कि पहला 'दूसरा' बहुत जल्द मुद्रण कर रहा था (एक मामले में, पहली बार .01 सेकंड के बाद) .. यह मेरी बैश सीखने की अवस्था का हिस्सा है ... मुझे आपका जवाब पसंद है, इसीलिए मैंने इस पर गहन विचार किया है।
पीटर

3

\rया \bदृष्टिकोणों के अलावा , \033[2K नियंत्रण चरित्र का उपयोग करना संभव है , जो टर्मिनल को पूरी रेखा को साफ करने के लिए कहता है। इसकी तुलना में इसका लाभ यह \bहै कि आपको उन \bवर्णों की संख्या से मेल नहीं खाना है , जिन्हें आप हटाना चाहते हैं और \rनई पंक्ति पुरानी से छोटी होने पर स्क्रीन पर चिपके हुए वर्ण नहीं होंगे। एक।

नीचे इस सवाल पर इसे कैसे लागू किया जा सकता है इसका उदाहरण है , और यहां बूट संदेशों के समान आउटपुट बनाने के लिए संबंधित एप्लिकेशन का एक उदाहरण है। इस विशेष उदाहरण में, टाइमर 0 वें सेकंड तक पहुंचने के बाद चला जाएगा और टाइमर लाइन को "रेडी!" से बदल दिया जाएगा। मुहावरा।

#!/bin/bash
sek=60
echo "60 Seconds"

while ((sek--)); do
    printf "One moment please: %d" "$sek"
    sleep 1
    printf "\r%b" "\033[2K"
done
echo "Ready!"

एक और विकल्प dialogकमांड-लाइन में सरल संवाद बनाने के लिए कमांड को नियोजित करना होगा । संवाद टाइमर की अवधि के लिए स्क्रीन पर रहेगा और लूप के साथ अपडेट होगा, और जब तक यह पूरा नहीं हो जाता है - टाइमर को सहज तरीके से संदेश के लिए "रेडी! प्रेस टू एग्जिट" से बदल दिया जाएगा:

#!/bin/bash
sek=60
echo "60 Seconds"

while ((sek--)); do
    echo "$sek" | dialog --progressbox "Please wait" 10 25
    sleep 1
done
dialog --msgbox "Ready! Press <OK> to finish" 10 25

dialogमैक पर मौजूद नहीं है: /
रिकी लेवी

1

यह वही है जो मैं यहाँ पढ़ने के बाद आया हूँ और थोड़ा और, एक लाइनर:

SEC=101;for i in `seq $SEC -1 1`;do printf "\rNext in: %`expr length $SEC`ds" "$i";sleep 1;done;echo

अधिक पठनीय:

#!/bin/bash
SEC=101

for i in `seq $SEC -1 1`;do
        printf "\rNext in: %`expr length $SEC`ds" "$i";
        sleep 1;
done
echo

जहां SEC को धनात्मक पूर्णांक पर सेट किया जा सकता है और प्रिंटफ उपयुक्त गद्दी का ध्यान रखेगा। उबंटू और साइबरविन के तहत परीक्षण किया गया।


1

कैरिज रिटर्न देकर इसे हासिल कर सकते हैं \r

कोड की एक पंक्ति में, यह संभव है echo -ne

for i in {60..1}; do echo -ne "One moment please: $i\r" && sleep 1; done

या के साथ printf

for i in {60..1}; do printf "One moment please: $i\r" && sleep 1; done

-2

उल्टी गिनती करने वाली घड़ी:

MIN=1 && for i in $(seq $(($MIN*60)) -1 1); do echo -n "$i, "; sleep 1; done; echo -e "nnMessage"

और 'सामान्य' स्टॉपवॉच है:

START=$( date +%s ); while true; do CURRENT=$( date +%s ) ; echo $(( CURRENT-START )) ; sleep 1 ; echo -n  ; done

नियंत्रण + सी रोकने के लिए


यह ओवरराइटिंग टेक्स्ट के बारे में सवाल का जवाब नहीं देता
जेरेमी केर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.