จะเปลี่ยนเนื้อหาของบรรทัดบนเทอร์มินัลได้อย่างไรเมื่อเทียบกับการเขียนใหม่?


24

ดังนั้นเมื่อwgetได้รับหน้าเว็บมันจะแสดงแถบสถานะที่ระบุจำนวนไฟล์ที่ดาวน์โหลด / ดาวน์โหลด ดูเหมือนว่านี้:

25%[=============>______________________________________] 25,000 100.0K/s (ขีดล่างเป็นช่องว่างฉันไม่สามารถหาวิธีที่จะได้พื้นที่มากกว่าหนึ่งช่องติดต่อกัน)

อย่างไรก็ตามแทนที่จะเขียนบรรทัดอื่นไปยัง stdout และเพิ่มแถบความคืบหน้าอีกอันบรรทัดนั้นจะอัพเดตเช่นนี้:

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

และwgetไม่ได้เป็นเพียงตัวอย่างเดียวของเรื่องนี้เช่นกัน ตัวอย่างเช่นเมื่อคุณไพพ์สิ่งใดสิ่งหนึ่งเข้าlessและออกแล้วพรอมต์ดั้งเดิมของคุณจะยังคงอยู่ที่นั่นพร้อมกับผลลัพธ์ของคำสั่งใดก็ตามที่คุณรันก่อนหน้านี้ มันเหมือนกับว่าคุณไม่เคยจากไป

ดังนั้นคำถามของฉันคือสิ่งนี้เรียกว่าฉันจะใช้มันได้อย่างไรมันทำงานได้ครั้งละหนึ่งบรรทัดเท่านั้นและฉันสามารถใช้มันใน C ได้ไหม?


5
ผมขอแนะนำให้อ่านBashFAQ 44 คุณอาจพบว่ามันน่าสนใจ
jw013

คำตอบ:


32

ก่อนอื่นคำถามของคุณไม่มีอะไรเกี่ยวข้องกับ bash แต่กับ terminal เทอร์มินัลกำลังตอบสนองต่อการแสดงข้อความของโปรแกรมและทุบตีตัวเองไม่สามารถควบคุมโปรแกรมได้เมื่อเปิดตัว

เทอร์มินัลนำเสนอลำดับการควบคุมเพื่อควบคุมสีแบบอักษรตำแหน่งเคอร์เซอร์และอื่น ๆ สำหรับรายการลำดับของเทอร์มินัลมาตรฐานดูที่ http://www.termsys.demon.co.uk/vtansi.htmคุณสามารถยกตัวอย่างได้

  • วางเคอร์เซอร์ที่ตำแหน่งเริ่มต้นของบรรทัด
  • ลบบรรทัดหลังจากนั้น
  • เขียนบรรทัดใหม่

เพื่อสร้างแถบความคืบหน้า

โดยทั่วไปแล้วลำดับการหลบหนีของเทอร์มินัลขั้นสูงขึ้นอยู่กับเทอร์มินัลเช่นทำงานกับ Eterm หรือ 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

วิธีเขียนทับบรรทัดที่มีอยู่โดยไม่มีลำดับของเทอร์มินัล

ทางออกที่ง่ายอย่างหนึ่งคือการไม่เขียนบรรทัดใหม่ในตอนท้าย แต่เขียน carriage return ซึ่งโดยทั่วไปจะรีเซ็ตเคอร์เซอร์ไปที่จุดเริ่มต้นของบรรทัดเช่น:

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

\rหรือกลับรถจะวางเคอร์เซอร์ที่จุดเริ่มต้นของเส้นและช่วยให้คุณสามารถเขียนทับเนื้อหาของบรรทัด

สลับระหว่างบัฟเฟอร์เช่นlessหรือvi

พฤติกรรมของlessยังเป็นเพราะคุณสมบัติขั้วขั้นสูงหน้าจอทางเลือก:

ในโหมด VT102 จะมี escape sequences เพื่อเปิดใช้งานและปิดใช้งานบัฟเฟอร์หน้าจอทางเลือกซึ่งมีขนาดเท่ากับพื้นที่แสดงผลของหน้าต่าง เมื่อเปิดใช้งานหน้าจอปัจจุบันจะถูกบันทึกและแทนที่ด้วยหน้าจอทางเลือก การบันทึกบรรทัดที่เลื่อนออกจากด้านบนของหน้าต่างถูกปิดใช้งานจนกว่าหน้าจอปกติจะได้รับการกู้คืน รายการ term‐ cap (5) สำหรับ xterm อนุญาตให้ visual editor vi (1) สลับไปที่หน้าจอทางเลือกสำหรับการแก้ไขและเรียกคืนหน้าจอเมื่อออก รายการเมนูป๊อปอัพทำให้ง่ายต่อการสลับไปมาระหว่างหน้าจอปกติและหน้าจออื่นสำหรับการตัดและวาง

http://rosettacode.org/wiki/Terminal_control/Preserve_screenจะแสดงตัวอย่างของวิธีการทำด้วยตัวคุณเองไม่ว่าจะผ่านทางtputหรือผ่านทาง escape sequences


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
เกล็นแจ็
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.