Як видалити рядок із відлунням?


60

Я знаю, що я міг видалити останні три символи за допомогою:

echo -ne '\b\b\b'

Але як я можу видалити повний рядок? Я маю на увазі, я не хочу використовувати:

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'

... і т.д. ..., щоб видалити довгий рядок.


2
Для тих, хто хотів би постійно писати на одному рядку: echo -ne "\033[2K" ; printf "\r"тепер рядок хороший як новий, наче він ніколи не писався раніше.
Hello World

2
Я впевнений, що ви можете просто скористатися echo -ne "\e[2K\r". Але тим не менше ANSI послідовності втечі FTW.
Парфянський розстріл

Відповіді:


57

Ви можете використовувати \bабо \rповернути курсор назад, а потім перезаписати друкований символ новим символом. Зауважте, що ні, \bні \rвидалено друковані символи. Він просто переміщує курсор назад. \bпереміщує курсор назад на один символ і \rпереміщує курсор на початок рядка.

Приклад: обидва

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

і

echo -e 'foooo\rbar'

надрукує:

baroo

Якщо ви хочете, щоб символи були видалені, вам доведеться скористатися наступним способом вирішення:

echo -e 'fooooo\r     \rbar'

вихід:

bar  

Витяг з 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
Так, але echo -e 'fooooooooo\rbarвідлуння barooooooo.
Мат

1
Так, ти правий. Зауважте, що echo -e 'foooo\b\b\b\b\b\b\b\b\b\bbar'також перегукується baroo.
lesmana

Так солодко, працює навіть бездоганно printf.
Майкл-О

4
Дуже неточна відповідь. Кевін справді кращий
Майк Аскі

87

Ви шукаєте термінальні втечі . Зокрема, для очищення від позиції курсора до початку рядка:

echo -e "\033[1K"

Або все в рядку, незалежно від положення курсору:

echo -e "\033[2K"

І ви можете робити всілякі інші акуратні трюки з термінальними втечами теж.


6
Це передбачає сумісний з VT100 термінал або емулятор (що є досить безпечним припущенням в наші дні).
Кіт Томпсон

2
Якщо ви хочете стерти щось, щойно повторилося, у вашому попередньому ехо повинен бути прапор -n, або ви будете відправлені в новий рядок
djjeck

1
Якщо ви хочете написати щось інше, у рядку, який ви стираєте, додайте прапор -n на відлуння вище, інакше ви перейдете до нового рядка відразу після його видалення. Крім того, додайте \ r до рядка вище, інакше ваш новий вміст не перейде до початку цього рядка.
djjeck

-1 | -eяк echoаргумент не сумісний з POSIX + мені не подобаються послідовності евакуації. Або віддайте перевагу, printfабо tput.
LinuxSecurityFreak

@Vlastimil, чому б ти спротив це? ОП не просила відповіді, яка б вам хотілася. Можливо, він повинен був уточнити, що цей -eпараметр echoне сумісний з POSIX, але все-таки ...
souki

35

Якщо ви хочете очистити лінію, то я пропоную вам скористатися комбінацією повернення вагона, про яку згадують люди та термінофо.

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

Це буде писати xyzzyxyzzy, потім повертатися до початку рядка і відправляти послідовність "ясно до кінця рядка" до терміналу, а потім записувати foobar. В -nмарці луни Не додає символ нового рядка після foobar.


4
Мені подобається така в майбутньому частина цього конкретного рішення - використання tput можливо означає, що воно буде працювати на будь-якому терміналі.
Амос Шапіра

2
Краще printf '%s\r%s%s' xyzzyxyzzy "$ceol" foobarщодо портативності та уникати вмісту, що $ceolпроходить через \xрозширення.
Стефан Шазелас

Найкраща відповідь хоча б тому, що вона працює з довільно довгими рядками. Дякую!
Рафаель

робота ідеальна. Але якщо я зміню розмір екрана терміналу менше, ніж вихідний рядок, він стає безладним.
K.Sopheak

11

Ви явно просите echo, але цей запит придушує вас. Ось підхід, який використовує вбудовану printfкоманду bash з розширенням дужок:

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

1
ідеально! саме те, що мені потрібно
Омар С.

2
printf 'Статус: розпочато'; сплячий час 2; printf '\ r'; printf 'Статус: оновлено'; сплячий режим 2s; printf '\ r';
Омар С.

4

Ось приклад, який використовує параметри ехо, не встановлюючи нову лінію-n та повернення каретки \r .

Баш перезаписувати термінальну лінію

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

Відмітка працює навіть на RHEL6. Приємно для чисто естетичних
праць

1

Замість цього echo -en "\r"ви можете також знайти printf "\r"команду як корисну. Таким чином ви можете відформатувати рядок. наприклад:

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

Зазвичай я це роблю і під час роботи з повільним розбором файлів для відображення поточного імені файлу без створення списку


-1 | Можливо, ви хотіли навмисно зробити однолінійку, але це насправді добре лише для тестування. Я б переписав це правильно новими рядками.
LinuxSecurityFreak

0

Як питання, видаліть повний рядок

Я використав команду нижче з комбінацією echoі sedдля видалення рядка

Після виконання команди команда буде порожньою, оскільки рядок буде замінено жодним

командування

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

Ось приклад таймера зворотного відліку, який я використовую:

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 | Можливо, ви хотіли навмисно зробити однолінійку, але це насправді добре лише для тестування. Я б переписав це правильно новими рядками.
LinuxSecurityFreak

Потім продовжуйте це робити і додайте нову відповідь. Або запропонувати редагувати мою відповідь.
mikiemorales
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.