बश का उपयोग करके टर्मिनल में अंतिम पंक्ति को कैसे हटाएं और प्रतिस्थापित करें?


99

मैं बैश में बीता हुआ सेकंड दिखाते हुए एक प्रगति पट्टी लागू करना चाहता हूं। इसके लिए, मुझे स्क्रीन पर दिखाई गई अंतिम पंक्ति को मिटाना होगा (कमांड "क्लियर" सभी स्क्रीन मिटा देता है, लेकिन मुझे केवल प्रगति पट्टी की लाइन को मिटाना होगा और इसे नई जानकारी से बदलना होगा)।

अंतिम परिणाम जैसा दिखना चाहिए:

$ Elapsed time 5 seconds

फिर 10 सेकंड के बाद मैं इस वाक्य को (स्क्रीन में उसी स्थिति में) बदलना चाहता हूं:

$ Elapsed time 15 seconds

जवाबों:


116

एक गाड़ी वापसी के साथ \ r गूंज

seq 1 1000000 | while read i; do echo -en "\r$i"; done

आदमी गूंज से:

-n     do not output the trailing newline
-e     enable interpretation of backslash escapes

\r     carriage return

19
for i in {1..100000}; do echo -en "\r$i"; doneseq कॉल से बचने के लिए :-)
डगलस लीडर

यह वही करता है जो मुझे चाहिए, धन्यवाद !! और seq कमांड का प्रयोग वास्तव में termianl जमा :-)
डिबगर

11
जब आप "in i for $ (...)" या "for i in {1..N}" जैसी चीजों का उपयोग करते हैं, तो आप पुनरावृति से पहले सभी तत्वों को उत्पन्न कर रहे हैं, जो कि बड़े इनपुट के लिए बहुत ही अक्षम है। आप या तो पाइपों का लाभ ले सकते हैं: "seq 1 100000 | जब मैं पढ़ता हूं; तो ..." या लूप के लिए बैश सी-स्टाइल का उपयोग करें: "के लिए ((i = 0 ;; i ++)); क्या ..."
टोकन

धन्यवाद डगलस और tokland - हालांकि अनुक्रम उत्पादन सीधे सवाल का हिस्सा नहीं था, मैं tokland के अधिक कुशल पाइप में बदल गया हूं
केन

1
मेरा मैट्रिक्स प्रिंटर पूरी तरह से मेरे कागज को गड़बड़ कर रहा है। यह कागज के एक ही टुकड़े पर डॉट्स को जाम रखता है जो अब नहीं है, यह कार्यक्रम कब तक चलता है?
रॉ

185

गाड़ी अपने आप लौटती है और केवल कर्सर को लाइन की शुरुआत में ले जाती है। यह ठीक है अगर आउटपुट की प्रत्येक नई लाइन कम से कम पहले वाली है, लेकिन यदि नई लाइन छोटी है, तो पिछली लाइन पूरी तरह से ओवरराइट नहीं होगी, जैसे:

$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz

नए पाठ के लिए वास्तव में लाइन को साफ करने के लिए, आप \033[Kनिम्नलिखित को जोड़ सकते हैं \r:

$ echo -e "abcdefghijklmnopqrstuvwxyz\r\033[K0123456789"
0123456789

http://en.wikipedia.org/wiki/ANSI_escape_code


3
यह मेरे वातावरण में वास्तव में अच्छा काम करता है। अनुकूलता का कोई ज्ञान?
अलेक्जेंडर ओलसन

21
बैश में कम से कम \e[Kइसके बजाय छोटा किया जा सकता है \033[K
डेव जेम्स मिलर

बहुत बढ़िया जवाब! माणिक से पुट का उपयोग पूरी तरह से करता है। अब मेरे टूलकिट का हिस्सा।
फतमान

@ द पिक्सेल डेवलपर: इसे बेहतर बनाने की कोशिश के लिए धन्यवाद, लेकिन आपका संपादन गलत था। कर्सर को लाइन की शुरुआत में ले जाने के लिए सबसे पहले वापसी करनी होगी, फिर मार उस कर्सर के स्थान से अंत तक पूरी लाइन को खाली कर देता है, जो पूरी लाइन को खाली कर देता है, जो कि इरादा है। आपने प्रत्येक नई पंक्ति की शुरुआत में, केन के उत्तर के समान, ताकि यह एक खाली रेखा पर लिखा हो।
डेरेक वेट

1
सिर्फ रिकॉर्ड के लिए, कोई इससे पहले \033[Gio भी कर सकता है हालांकि स्पष्ट रूप से बहुत सरल है। इसके अलावा invisible-island.net/xterm/ctlseqs/ctlseqs.html विकिपीडिया की तुलना में अधिक विवरण देता है और टर्म डेवलपर की ओर से है। \r\033[K\r
जमदग्नि

19

डेरेक वीट का जवाब अच्छी तरह से काम करता है जब तक कि लाइन की लंबाई टर्मिनल चौड़ाई से अधिक न हो। यदि यह स्थिति नहीं है, तो निम्न कोड जंक आउटपुट को रोक देगा:

पहली बार लाइन लिखे जाने से पहले करें

tput sc

जो वर्तमान कर्सर स्थिति को बचाता है। अब जब भी आप अपनी लाइन प्रिंट करना चाहते हैं, उपयोग करें

tput rc
tput ed
echo "your stuff here"

पहले सहेजे गए कर्सर की स्थिति में लौटने के लिए, फिर स्क्रीन को कर्सर से नीचे तक साफ़ करें, और अंत में आउटपुट लिखें।


व्यर्थ, यह टर्मिनेटर में कुछ भी नहीं करता है। क्या आपको पता है कि संगतता सीमाएँ हैं?
जेमी पाटे

1
Cygwin के लिए ध्यान दें: आपको "tput" का उपयोग करने के लिए पैकेज "ncurses" स्थापित करने की आवश्यकता है।
जैक मिलर

हम्म ... लगता है कि अगर काम नहीं करता है तो एक लाइन आउटपुट में है। यह काम नहीं करता है:tput sc # save cursor echo '' > sessions.log.json while [ 1 ]; do curl 'http://localhost/jolokia/read/*:type=Manager,*/activeSessions,maxActiveSessions' >> sessions.log.json echo '' >> sessions.log.json cat sessions.log.json | jq '.' tput rc;tput el # rc = restore cursor, el = erase to end of line sleep 1 done
Nux

@ नक्स आपको tput edइसके बजाय उपयोग करने की आवश्यकता है tput el। @ उम के उदाहरण का इस्तेमाल किया ed(शायद उसने आपकी टिप्पणी के बाद इसे ठीक किया)।
स्टूजेक

FYI करें, यहाँ tput कमांड्स की सूची है कलर्स और कर्सर मूवमेंट विथ tput
studgeek

12

मेरे लिए \ 033 विधि काम नहीं आई। \ R तरीका काम करता है, लेकिन यह वास्तव में कुछ भी नहीं मिटाता है, बस लाइन की शुरुआत में कर्सर डालता है। इसलिए यदि नया तार पुराने से छोटा है तो आप पंक्ति के अंत में बचे हुए पाठ को देख सकते हैं। अंत में tput सबसे अच्छा रास्ता तय करना था। यह कर्सर सामान के अलावा अन्य उपयोग करता है और यह कई लिनक्स और बीएसडी डिस्ट्रो में पहले से इंस्टॉल आता है इसलिए यह अधिकांश बैश उपयोगकर्ताओं के लिए उपलब्ध होना चाहिए।

#/bin/bash
tput sc # save cursor
printf "Something that I made up for this string"
sleep 1
tput rc;tput el # rc = restore cursor, el = erase to end of line
printf "Another message for testing"
sleep 1
tput rc;tput el
printf "Yet another one"
sleep 1
tput rc;tput el

यहाँ थोड़ी उलटी गिनती स्क्रिप्ट के साथ खेलने के लिए है:

#!/bin/bash
timeout () {
    tput sc
    time=$1; while [ $time -ge 0 ]; do
        tput rc; tput el
        printf "$2" $time
        ((time--))
        sleep 1
    done
    tput rc; tput ed;
}

timeout 10 "Self-destructing in %s"

यह पूरी लाइन को साफ करता है, समस्या यह है कि यह मेरे लिए बहुत अधिक
ट्विंकल है

5

यदि प्रगति आउटपुट मल्टी लाइन है, या स्क्रिप्ट ने पहले से ही नई लाइन कैरेक्टर को प्रिंट कर लिया है, तो आप लाइनों को कुछ इस तरह से जोड़ सकते हैं:

printf "\033[5A"

जो कर्सर को 5 लाइनों को ऊपर करने के लिए बनाएगा। फिर आपको जो कुछ भी ज़रूरत है उसे ओवरराइट कर सकते हैं।

अगर वह काम नहीं करेगा तो आप कोशिश कर सकते हैं printf "\e[5A"या echo -e "\033[5A", जिसका प्रभाव समान होना चाहिए।

मूल रूप से, भागने के दृश्यों के साथ आप स्क्रीन में लगभग सब कुछ नियंत्रित कर सकते हैं।


इसके बराबर का पोर्टेबल है tput cuu 5, जहां 5 पंक्तियों की संख्या है ( cuuऊपर जाने के लिए, cudनीचे जाने के लिए)।
मैलान

4

गाड़ी वापसी चरित्र का उपयोग करें:

echo -e "Foo\rBar" # Will print "Bar"

यह उत्तर सबसे सरल तरीका है। तुम भी एक ही प्रभाव का उपयोग कर प्राप्त कर सकते हैं: Printf "फू \ rBar"
lee8oi

1

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

कोड की एक पंक्ति में printf

for i in {10..1}; do printf "Counting down: $i\r" && sleep 1; done

या के साथ echo -ne

for i in {10..1}; do echo -ne "Counting down: $i\r" && sleep 1; done
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.