Câu hỏi Làm thế nào để xóa và thay thế dòng cuối cùng trong thiết bị đầu cuối bằng cách sử dụng bash?


Tôi muốn thực hiện một thanh tiến trình hiển thị giây trôi qua trong bash. Đối với điều này, tôi cần phải xóa dòng cuối cùng hiển thị trên màn hình (lệnh "xóa" xóa tất cả màn hình, nhưng tôi chỉ cần xóa dòng của thanh tiến trình và thay thế nó bằng thông tin mới).

Kết quả cuối cùng sẽ như sau:

$ Elapsed time 5 seconds

Sau 10 giây tôi muốn thay thế câu này (ở cùng vị trí trên màn hình) bằng cách:

$ Elapsed time 15 seconds

75
2018-03-05 16:06


gốc




Các câu trả lời:


echo một trở về vận chuyển với \ r

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

từ tiếng vang của người đàn ông:

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

\r     carriage return

97
2018-03-05 16:08



for i in {1..100000}; do echo -en "\r$i"; done để tránh cuộc gọi seq :-) - Douglas Leeder
Điều này thực hiện chính xác những gì tôi cần, cảm ơn !! Và việc sử dụng lệnh seq thực sự đóng băng termianl :-) - Debugger
Khi bạn sử dụng những thứ như "for i in $ (...)" hoặc "for i in {1..N}", bạn đang tạo ra tất cả các phần tử trước khi lặp lại, điều đó rất không hiệu quả đối với các đầu vào lớn. Bạn có thể tận dụng lợi thế của đường ống: "seq 1 100000 | while read i; do ..." hoặc sử dụng bash c-style cho vòng lặp: "for ((i = 0 ;; i ++)); do ..." - tokland
Cũng giống như những máy đánh chữ cũ tốt. - aggregate1166877
Máy in ma trận của tôi là hoàn toàn rối tung lên giấy của tôi. Nó giữ các chấm kẹt trên cùng một mảnh giấy không còn ở đó nữa, chương trình này chạy trong bao lâu? - Rob Quist


Việc vận chuyển trở lại của chính nó chỉ di chuyển con trỏ đến đầu dòng. Đó là OK nếu mỗi dòng đầu ra mới ít nhất là dòng trước đó, nhưng nếu dòng mới ngắn hơn, dòng trước đó sẽ không được ghi đè hoàn toàn, ví dụ:

$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz

Để thực sự xóa dòng cho văn bản mới, bạn có thể thêm \033[K sau \r:

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

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


155
2017-07-21 10:06



Điều này hoạt động thực sự tốt trong môi trường của tôi. Bất kỳ kiến ​​thức về khả năng tương thích? - Alexander Olsson
Trong Bash ít nhất có thể rút ngắn \e[K thay vì \033[K. - Dave James Miller
Câu trả lời chính xác! Hoạt động hoàn hảo bằng cách sử dụng đặt từ ruby. Bây giờ là một phần của bộ công cụ của tôi. - phatmann
+1 để xóa văn bản - chepner
Chỉ để ghi lại, người ta cũng có thể làm \033[G i.o. \r trước \033[K mặc dù rõ ràng \r đơn giản hơn nhiều. Cũng thế invisible-island.net/xterm/ctlseqs/ctlseqs.html cung cấp thêm chi tiết hơn Wikipedia và là từ nhà phát triển xterm. - jamadagni


Câu trả lời của Derek Veit hoạt động tốt miễn là chiều dài dòng không bao giờ vượt quá chiều rộng đầu cuối. Nếu đây không phải là trường hợp, đoạn mã sau sẽ ngăn chặn đầu ra rác:

trước khi dòng được viết lần đầu tiên, hãy làm

tput sc

lưu vị trí con trỏ hiện tại. Bây giờ bất cứ khi nào bạn muốn in dòng của mình, hãy sử dụng

tput rc
tput ed
echo "your stuff here"

đầu tiên quay trở lại vị trí con trỏ đã lưu, sau đó xóa màn hình từ con trỏ xuống cuối và cuối cùng viết đầu ra.


16
2017-09-20 12:04



Cảm ơn rất nhiều! +1 - AndreasT
Wierd, điều này không có gì trong terminator. Bạn có biết nếu có những hạn chế về khả năng tương thích? - Jamie Pate
Lưu ý cho Cygwin: Bạn cần cài đặt gói "ncurses" để sử dụng "tput". - Jack Miller
Hừm ... Có vẻ như không làm việc nếu có thêm một dòng ở đầu ra. Điều này không hoạt động: 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
@Nux Bạn cần sử dụng tput ed thay vì tput el. Ví dụ của @ Um được sử dụng ed (có lẽ anh ấy đã sửa nó sau khi bạn nhận xét). - studgeek


Phương pháp \ 033 không hoạt động đối với tôi. Phương thức \ r hoạt động nhưng nó không thực sự xóa bất cứ thứ gì, chỉ cần đặt con trỏ ở đầu dòng. Vì vậy, nếu chuỗi mới ngắn hơn so với cái cũ bạn có thể thấy văn bản còn sót lại ở cuối dòng. Cuối cùng, tput là cách tốt nhất để đi. Nó có các ứng dụng khác bên cạnh các công cụ con trỏ cộng với nó được cài đặt sẵn trong nhiều bản phân phối Linux & BSD nên nó sẽ có sẵn cho hầu hết người dùng bash.

#/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

Đây là một kịch bản đếm ngược nhỏ để chơi với:

#!/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"

10
2018-01-14 20:45



Điều đó rõ ràng toàn bộ dòng thực sự, vấn đề nó lấp lánh quá nhiều cho tôi: '( - smarber


Sử dụng ký tự trả về vận chuyển:

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

4
2018-03-05 16:09



Câu trả lời này là cách đơn giản nhất. Bạn thậm chí có thể đạt được hiệu quả tương tự bằng cách sử dụng: printf "Foo \ rBar" - lee8oi


Trong trường hợp đầu ra tiến trình là nhiều dòng, hoặc tập lệnh sẽ đã in ký tự dòng mới, bạn có thể nhảy dòng lên với một cái gì đó như:

printf "\033[5A"

mà sẽ làm cho con trỏ nhảy lên 5 dòng. Sau đó, bạn có thể ghi đè lên bất cứ điều gì bạn cần.

Nếu điều đó không hiệu quả, bạn có thể thử printf "\e[5A" hoặc là echo -e "\033[5A", nên có cùng tác dụng.

Về cơ bản, với trình tự thoát bạn có thể kiểm soát hầu hết mọi thứ trên màn hình.


2
2018-05-19 22:16





Cách đơn giản nhất là sử dụng \r nhân vật tôi đoán.

Hạn chế là bạn không thể có các dòng hoàn chỉnh, vì nó chỉ xóa dòng hiện tại.

Ví dụ đơn giản:

time=5
echo -n "Elapsed $time seconds"
sleep 10
time=15
echo -n "Elapsed $time seconds"

echo "\nDone"

-1
2018-03-05 16:13



Um, nhưng ví dụ của bạn không xóa và thay thế dòng cuối cùng, đó là những gì OP yêu cầu. - jamadagni