Как удалить строку с эхо?


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"теперь строка хороша как новая, как если бы она никогда не была написана раньше.
Привет, мир,

2
Я уверен, что вы можете просто использовать echo -ne "\e[2K\r". Но ANSI escape-последовательности 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.
Michael-O

4
Очень неточный ответ. Кевин один действительно лучше
Майк Аски

88

Вы ищете терминальные побеги . В частности, очистить от позиции курсора до начала строки:

echo -e "\033[1K"

Или все в строке, независимо от положения курсора:

echo -e "\033[2K"

И вы можете делать все другие аккуратные трюки с терминальными выходами тоже.


6
Это предполагает VT100-совместимый терминал или эмулятор (что является довольно безопасным предположением в наши дни).
Кит Томпсон

2
Если вы хотите стереть что-то, что вы только что повторили, у вашего предыдущего эха должен быть флаг -n, или вы будете
перенаправлены

1
Если вы хотите написать что-то еще, в строке, которую вы стираете, добавьте флаг -n в эхо выше, иначе вы перейдете на новую строку сразу после удаления. Кроме того, добавьте \ r к приведенной выше строке, иначе ваш новый контент не попадет в начало этой строки.
djjeck

-1 | -eкак echoаргумент не соответствует POSIX + мне не нравятся escape-последовательности. Либо предпочитаю, printfлибо tput.
LinuxSecurityFreak

@Vlastimil почему бы тебе понизить это? ОП не спрашивал ответа, который бы вы хотели получить. Возможно, ему следовало уточнить, что -eпараметр for echoне соответствует POSIX, но все же ...
souki

35

Если вы хотите очистить линию, я предлагаю вам использовать комбинацию возврата каретки, которую упоминают люди и terminfo.

# 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расширение.
Стефан Шазелас

Лучший ответ хотя бы потому, что он работает с произвольно длинными строками. Спасибо!
Рафаэль

работать отлично. Но если я изменю размер экрана терминала меньше выходной линии, он становится грязным.
К.Софис

11

Вы явно просите echo, но этот запрос ограничивает вас. Вот подход, который использует встроенную printfкоманду bash с расширением скобок:

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

1
идеальный! именно то, что мне было нужно
Омар С.

2
printf 'Статус: запущен'; sleep 2s; printf '\ r'; printf 'Статус: обновлен'; sleep 2s; printf '\ r';
Омар С.

4

Вот пример использования echo без перевода строки -n и возврата каретки \r .

bash перезаписать клеммную линию

#!/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чтобы удалить строку

После выполнения команды результат будет пустым. Поскольку строка будет заменена на none

команда

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.