Làm thế nào để thay đổi nội dung của một dòng trên thiết bị đầu cuối trái ngược với việc viết một dòng mới?


24

Vì vậy, khi wgetcó một trang web, nó hiển thị cho bạn một thanh trạng thái cho biết số lượng tệp được tải xuống. Nó trông như thế này:

25%[=============>______________________________________] 25,000 100.0K/s (dấu gạch dưới là khoảng trắng; tôi không thể tìm ra cách lấy nhiều hơn một khoảng trống liên tiếp ở đó)

Tuy nhiên, thay vì viết một dòng khác vào thiết bị xuất chuẩn và thêm một thanh tiến trình khác, nó sẽ cập nhật nó, như sau:

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

wgetcũng không phải là ví dụ duy nhất về điều này. Ví dụ: khi bạn đưa một cái gì đó vào lessrồi thoát, dấu nhắc ban đầu của bạn vẫn ở đó, cùng với kết quả của bất kỳ lệnh nào bạn đã chạy trước đó. Nó giống như bạn không bao giờ rời đi.

Vì vậy, câu hỏi của tôi là, cái này được gọi là gì, làm thế nào để tôi thực hiện nó, nó chỉ hoạt động cho một dòng duy nhất tại một thời điểm và tôi có thể sử dụng nó trong C không?


5
Tôi khuyên bạn nên đọc BashFAQ 44 . Bạn có thể thấy nó thú vị.
jw013

Câu trả lời:


32

Trước hết câu hỏi của bạn không liên quan gì đến bash nhưng với thiết bị đầu cuối. Thiết bị đầu cuối đang phản hồi để hiển thị văn bản của các chương trình và bản thân bash không có quyền kiểm soát các chương trình khi chúng khởi chạy.

Thiết bị đầu cuối cung cấp các chuỗi điều khiển để kiểm soát màu sắc, phông chữ, vị trí con trỏ và hơn thế nữa. Để biết danh sách các trình tự đầu cuối được tiêu chuẩn hóa, hãy xem http://www.termsys.demon.co.uk/vtansi.htm Bạn có thể lấy ví dụ

  • định vị con trỏ ở đầu dòng
  • xóa dòng sau đó
  • viết một dòng mới

để tạo một thanh tiến trình.

Trình tự thoát thiết bị đầu cuối tiên tiến hơn thường phụ thuộc vào thiết bị đầu cuối, ví dụ: chỉ hoạt động với Eterm hoặc xterm. lời khuyên - là một thư viện lập trình để tạo các chương trình tương tác với thiết bị đầu cuối, do đó bạn sẽ không phải sử dụng các chuỗi thoát.

Làm thế nào để ghi đè lên một dòng hiện có với trình tự đầu cuối

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

Làm thế nào để ghi đè lên một dòng hiện có mà không có trình tự đầu cuối

Một giải pháp đơn giản là không viết một dòng mới ở cuối mà viết trở lại vận chuyển, về cơ bản đặt lại con trỏ về đầu dòng, ví dụ:

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

Trả về \rhoặc vận chuyển sẽ đặt con trỏ ở đầu dòng và cho phép bạn ghi đè lên nội dung của dòng.

Chuyển đổi giữa các bộ đệm như lesshoặcvi

Hành vi của lesscũng là do một tính năng thiết bị đầu cuối tiên tiến hơn, màn hình thay thế:

Trong chế độ VT102, có các chuỗi thoát để kích hoạt và hủy kích hoạt bộ đệm màn hình thay thế, có cùng kích thước với khu vực hiển thị của cửa sổ. Khi được kích hoạt, màn hình hiện tại được lưu và thay thế bằng màn hình thay thế. Việc lưu các dòng được cuộn từ trên cùng của cửa sổ bị vô hiệu hóa cho đến khi màn hình bình thường được phục hồi. Mục nhập hạn (5) cho xterm cho phép trình soạn thảo trực quan vi (1) chuyển sang màn hình thay thế để chỉnh sửa và khôi phục màn hình khi thoát. Một mục menu bật lên giúp đơn giản để chuyển đổi giữa màn hình bình thường và thay thế để cắt và dán.

http://rosettacode.org/wiki/Terminal_control/Preserve_screen liệt kê một số ví dụ làm thế nào để làm điều đó cho mình, hoặc thông qua tput hoặc thông qua một số trình tự thoát.


15

Thay vì sử dụng echotự động nối thêm một dòng mới vào chuỗi, hãy sử dụng printf "%s\r" whatever- trả về vận chuyển sẽ gửi con trỏ đến đầu dòng hiện tại. thí dụ:

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

tùy thuộc vào con trỏ của thiết bị đầu cuối của bạn, có thể sẽ dễ chịu hơnprintf "\r%2d " $num
glenn jackman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.