Làm thế nào để xóa dòng với echo?


60

Tôi biết rằng tôi có thể xóa ba ký tự cuối cùng với:

echo -ne '\b\b\b'

Nhưng làm thế nào tôi có thể xóa một dòng đầy đủ? Ý tôi là tôi không muốn sử dụng:

echo -ne '\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b'

... vv ... để xóa một dòng dài.


2
Đối với những người muốn liên tục viết trên cùng một dòng : echo -ne "\033[2K" ; printf "\r", bây giờ dòng này tốt như mới, như thể nó chưa bao giờ được viết trước đó.
Xin chào thế giới

2
Tôi khá chắc chắn rằng bạn chỉ có thể sử dụng echo -ne "\e[2K\r". Nhưng ANSI thoát khỏi trình tự FTW, dù sao.
Bắn Parthian

Câu trả lời:


57

Bạn có thể sử dụng \bhoặc \rđể di chuyển con trỏ trở lại và sau đó ghi đè ký tự được in bằng một ký tự mới. Lưu ý rằng không xóa \bcũng không \rxóa các ký tự in. Nó chỉ di chuyển con trỏ trở lại. \bdi chuyển con trỏ trở lại một ký tự và \rdi chuyển con trỏ đến đầu dòng.

Ví dụ: cả hai

echo -e 'foooo\b\b\b\b\bbar'

echo -e 'foooo\rbar'

sẽ in:

baroo

Nếu bạn muốn xóa các ký tự thì bạn phải sử dụng cách giải quyết sau:

echo -e 'fooooo\r     \rbar'

đầu ra:

bar  

Trích từ man echo:

   If -e is in effect, the following sequences are recognized:

   \0NNN  the character whose ASCII code is NNN (octal)

   \\     backslash

   \a     alert (BEL)

   \b     backspace

   \c     produce no further output

   \f     form feed

   \n     new line

   \r     carriage return

   \t     horizontal tab

   \v     vertical tab

   NOTE: your shell may have its own version of echo, which usually super‐
   sedes the version described here.  Please refer to your  shell's  docu‐
   mentation for details about the options it supports.

4
Có, nhưng echo -e 'fooooooooo\rbartiếng vang barooooooo.
Mat

1
Có bạn đúng. Lưu ý rằng echo -e 'foooo\b\b\b\b\b\b\b\b\b\bbar'cũng vang vọng baroo.
lesmana

Thật ngọt ngào, làm việc thậm chí hoàn hảo trong printf.
Michael-O

4
Câu trả lời rất không chính xác. Kevin's one thực sự tốt hơn
Mike Aski

87

Bạn đang tìm kiếm lối thoát thiết bị đầu cuối . Cụ thể, để xóa từ vị trí con trỏ đến đầu dòng:

echo -e "\033[1K"

Hoặc mọi thứ trên dòng, bất kể vị trí con trỏ:

echo -e "\033[2K"

Và bạn cũng có thể thực hiện tất cả các loại thủ thuật gọn gàng khác với thiết bị đầu cuối thoát.


6
Điều này giả định một thiết bị đầu cuối hoặc trình giả lập tương thích VT100 (đây là một giả định khá an toàn hiện nay).
Keith Thompson

2
Nếu bạn muốn xóa một cái gì đó bạn vừa lặp lại, tiếng vang trước đó của bạn phải có cờ -n hoặc bạn sẽ được gửi đến một dòng mới
djjeck

1
Nếu bạn muốn viết một cái gì đó khác, trên dòng bạn đang xóa, hãy thêm cờ -n vào tiếng vang ở trên, nếu không bạn sẽ chuyển sang một dòng mới ngay sau khi xóa nó. Ngoài ra, nối thêm \ r vào chuỗi ở trên hoặc nội dung mới của bạn sẽ không đi đến đầu dòng đó.
djjeck

-1 | -eechođối số không tuân thủ POSIX + Tôi không thích các chuỗi thoát. Hoặc là thích printfhoặc tput.
LinuxSecurityFreak

@Vlastimil tại sao bạn lại downvote này? OP đã không yêu cầu một câu trả lời mà bạn muốn. Có lẽ anh ta nên cho rằng -etham số đó echokhông tuân thủ POSIX nhưng vẫn ...
souki

35

Nếu bạn muốn xóa dòng, thì tôi khuyên bạn nên sử dụng kết hợp vận chuyển trở lại mà mọi người đang đề cập và terminfo.

# terminfo clr_eol
ceol=$(tput el)
echo -ne "xyzzyxyzzy\r${ceol}foobar"

Điều này sẽ viết xyzzyxyzzy, sau đó quay trở lại đầu dòng và gửi chuỗi "xóa đến cuối dòng" đến thiết bị đầu cuối, sau đó viết foobar. Các -necho làm cho không thêm một dòng mới sau foobar.


4
Tôi thích loại phần chứng minh tương lai của giải pháp cụ thể này - sử dụng thuật ngữ có thể có nghĩa là nó sẽ hoạt động trên bất kỳ loại thiết bị đầu cuối nào.
Amos Shapira

2
Tốt hơn là printf '%s\r%s%s' xyzzyxyzzy "$ceol" foobarcho tính di động và để tránh có nội dung $ceoltrải qua \xmở rộng.
Stéphane Chazelas

Câu trả lời tốt nhất nếu chỉ vì nó hoạt động với các dòng dài tùy ý. Cảm ơn!
Raphael

làm việc hoàn hảo Nhưng nếu tôi thay đổi kích thước màn hình thiết bị đầu cuối nhỏ hơn dòng đầu ra, nó sẽ trở nên lộn xộn.
K.Sopheak

11

Bạn yêu cầu rõ ràng echo, nhưng yêu cầu này ghim bạn xuống. Đây là một cách tiếp cận sử dụng printflệnh dựng sẵn của bash với mở rộng cú đúp:

printf 'fooooooooo' # 10 characters
printf '\r'; printf ' %0.s' {0..9} # 10 expansions of the space character

1
hoàn hảo! chính xác những gì tôi cần
Omar S.

2
printf 'Trạng thái: đã bắt đầu'; ngủ 2s; printf '\ r'; printf 'Trạng thái: đã cập nhật'; ngủ 2s; printf '\ r';
Omar S.

4

Đây là một ví dụ sử dụng echo không có tùy chọn hoàn trả dòng mới-nvận chuyển \r .

bash ghi đè dòng thiết bị đầu cuối

#!/bin/bash

CHECK_MARK="\033[0;32m\xE2\x9C\x94\033[0m"

echo -e "\n\e[4mDoing Things\e[0m"
echo -n "doing thing 1..."
sleep 1
echo -e "\\r${CHECK_MARK} thing 1 done"

Dấu kiểm hoạt động ngay cả trên RHEL6. Rất thích hợp cho các chỉnh sửa hoàn toàn về mặt thẩm mỹ của các kịch bản của tôi
oneindelijk

1

Thay vì echo -en "\r"bạn cũng có thể tìm thấy printf "\r"lệnh là hữu ích. Bằng cách này bạn có thể định dạng chuỗi. ví dụ:

for sec in {1..100}; do printf "\r %04d" ${sec}; sleep 0.1; done

Tôi cũng thường làm điều đó khi hoạt động với phân tích tệp chậm để hiển thị tên tệp hiện đang xử lý mà không tạo danh sách


-1 | Có thể bạn muốn cố tình tạo một lớp lót, nhưng điều đó thực sự chỉ tốt cho thử nghiệm. Tôi sẽ viết lại nó đúng cách với các dòng mới.
LinuxSecurityFreak

0

Như câu hỏi là xóa dòng đầy đủ

Tôi đã sử dụng lệnh dưới đây với sự kết hợp của echosedđể xóa dòng

Sau khi thực hiện kết quả lệnh sẽ là void.since trong khi dòng sẽ được thay thế bằng none

chỉ huy

echo  "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" | sed -r "s/.*//g"

-1

Dưới đây là ví dụ về đồng hồ đếm ngược mà tôi sử dụng:

i=10
while [ $i -gt 0 ]; 
do 
  printf "$i seconds remaining       " && printf '\r\033[1B'
  i=`expr $i - 1`
  sleep 1
  printf '\033[1A'
done

-1 | Có thể bạn muốn cố tình tạo một lớp lót, nhưng điều đó thực sự chỉ tốt cho thử nghiệm. Tôi sẽ viết lại nó đúng cách với các dòng mới.
LinuxSecurityFreak

Sau đó, tiếp tục và làm điều đó và thêm một câu trả lời mới. Hoặc đề nghị chỉnh sửa câu trả lời của tôi.
mikiemorales
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.