एक नया लिखने के विपरीत टर्मिनल पर एक लाइन की सामग्री को कैसे बदला जाए?


24

इसलिए, जब wgetकोई वेब पेज मिलता है, तो यह आपको एक स्टेटस बार दिखाता है, जो बताता है कि फाइल कितनी है / डाउनलोड की गई है। यह इस तरह दिख रहा है:

25%[=============>______________________________________] 25,000 100.0K/s (अंडरस्कोर स्पेस हैं; मैं अभी यह पता नहीं लगा सका कि वहाँ एक से अधिक लगातार स्पेस कैसे प्राप्त करें)

हालाँकि, एक और प्रगति पट्टी को जोड़ने और दूसरी प्रगति पट्टी को लिखने के बजाय, यह इसे इस तरह अपडेट करता है:

50%[===========================>________________________] 50,000 100.0K/s

और wgetइसका एकमात्र उदाहरण नहीं है। उदाहरण के लिए, जब आप किसी चीज़ को पाइप में डालते हैं lessऔर फिर बाहर निकलते हैं, तो आपका मूल संकेत अभी भी मौजूद है, साथ ही जो कुछ भी आप पहले चलाते थे, उसके परिणाम के साथ। यह ऐसा है जैसे तुमने कभी छोड़ा नहीं।

तो, मेरे सवाल हैं, इसे क्या कहा जाता है, मैं इसे कैसे लागू करूं, क्या यह केवल एक बार में एक पंक्ति के लिए काम करता है, और क्या मैं इसे सी में उपयोग कर सकता हूं?


5
मैं बशफा 44 को पढ़ने की सलाह देता हूं । आपको यह दिलचस्प लग सकता है।
jw013

जवाबों:


32

सबसे पहले आपके प्रश्न का बाश के साथ लेकिन टर्मिनल के साथ कोई लेना देना नहीं है। टर्मिनल कार्यक्रमों के पाठ को प्रदर्शित करने के लिए प्रतिक्रिया दे रहा है और एक बार लॉन्च होने के बाद खुद को प्रोग्राम पर कोई नियंत्रण नहीं है।

टर्मिनल रंग, फ़ॉन्ट, कर्सर स्थिति और अधिक को नियंत्रित करने के लिए नियंत्रण अनुक्रम प्रदान करते हैं। मानकीकृत टर्मिनल अनुक्रमों की सूची के लिए http://www.termsys.demon.co.uk/vtansi.htm पर एक नज़र डाल सकते हैं।

  • लाइन की शुरुआत में कर्सर रखें
  • बाद में लाइन हटाएं
  • एक नई लाइन लिखें

एक प्रगति पट्टी बनाने के लिए।

अधिक उन्नत टर्मिनल एस्केप सीक्वेंस आमतौर पर टर्मिनल पर निर्भर होते हैं, उदाहरण के लिए केवल एटरम या xterm के साथ काम करते हैं। ncurses - एक प्रोग्रामिंग लाइब्रेरी है जो टर्मिनल के साथ इंटरैक्टिव प्रोग्राम बनाने के लिए है ताकि आपको एस्केप सीक्वेंस का उपयोग न करना पड़े।

टर्मिनल अनुक्रमों के साथ एक मौजूदा रेखा को कैसे अधिलेखित करें

echo long text
sleep 1
printf "\033[1A"  # move cursor one line up
printf "\033[K"   # delete till end of line
echo foo

टर्मिनल अनुक्रम के बिना किसी मौजूदा लाइन को कैसे अधिलेखित करें

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

echo -n first 
sleep 1 
echo -ne "\rsecond"
echo

\rया गाड़ी वापसी पंक्ति के आरंभ में कर्सर रखें और आप लाइन से सामग्री को अधिलेखित करने की अनुमति देता होगा।

जैसे बफ़र्स के बीच स्विच करें lessयाvi

का व्यवहार lessएक अधिक उन्नत टर्मिनल सुविधा, वैकल्पिक स्क्रीन के कारण भी है:

VT102 मोड में, वैकल्पिक स्क्रीन बफर को सक्रिय और निष्क्रिय करने के लिए एस्केप सीक्वेंस हैं, जो कि विंडो के डिस्प्ले क्षेत्र के समान आकार है। सक्रिय होने पर, वर्तमान स्क्रीन को बचाया जाता है और वैकल्पिक स्क्रीन के साथ बदल दिया जाता है। सामान्य स्क्रीन को पुनर्स्थापित करने तक विंडो के शीर्ष पर स्क्रॉल की गई लाइनों को सहेजना अक्षम है। शब्द के लिए टर्म कैप (5) प्रविष्टि दृश्य संपादक vi (1) को संपादन के लिए वैकल्पिक स्क्रीन पर स्विच करने और बाहर निकलने पर स्क्रीन को पुनर्स्थापित करने की अनुमति देता है। एक पॉपअप मेनू प्रविष्टि कट और पेस्ट के लिए सामान्य और वैकल्पिक स्क्रीन के बीच स्विच करना आसान बनाती है।

http://rosettacode.org/wiki/Terminal_control/Preserve_screen कुछ उदाहरणों की सूची देता है कि इसे कैसे करना है, या तो tput के माध्यम से या कुछ एस्केप दृश्यों के माध्यम से।


15

उपयोग करने के बजाय echoजो स्वचालित रूप से स्ट्रिंग के लिए एक नई रेखा को जोड़ता है, का उपयोग करें printf "%s\r" whatever- गाड़ी वापसी वर्तमान लाइन की शुरुआत में कर्सर भेजती है। उदाहरण:

seq 1 15 | while read num; do printf "%2d\r" $num; sleep 1; done; echo ""

आपके टर्मिनल के कर्सर के आधार पर, यह करने के लिए अधिक सुखदायक हो सकता हैprintf "\r%2d " $num
ग्लेन जैकमैन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.