Ответ 1
повторите возврат каретки с помощью \r
seq 1 1000000 | while read i; do echo -en "\r$i"; done
из эха человека:
-n do not output the trailing newline
-e enable interpretation of backslash escapes
\r carriage return
Я хочу реализовать индикатор выполнения, показывающий прошедшие секунды в bash. Для этого мне нужно удалить последнюю строку, показанную на экране (команда "clear" стирает весь экран, но мне нужно удалить только строку индикатора выполнения и заменить ее новой информацией).
Конечный результат должен выглядеть так:
$ Elapsed time 5 seconds
Затем через 10 секунд я хочу заменить это предложение (в том же положении на экране):
$ Elapsed time 15 seconds
повторите возврат каретки с помощью \r
seq 1 1000000 | while read i; do echo -en "\r$i"; done
из эха человека:
-n do not output the trailing newline
-e enable interpretation of backslash escapes
\r carriage return
Возвращение каретки только перемещает курсор в начало строки. Это нормально, если каждая новая строка вывода не меньше, чем предыдущая, но если новая строка короче, предыдущая строка не будет полностью перезаписана, например:
$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz
Чтобы действительно очистить строку для нового текста, вы можете добавить \033[K
после \r
:
$ echo -e "abcdefghijklmnopqrstuvwxyz\r\033[K0123456789"
0123456789
Ответ Derek Veit работает хорошо, если длина линии никогда не превышает ширину терминала. Если это не так, следующий код предотвратит нежелательный вывод:
прежде чем строка будет записана в первый раз, do
tput sc
который сохраняет текущую позицию курсора. Теперь, когда вы хотите распечатать свою строку, используйте
tput rc
tput ed
echo "your stuff here"
чтобы сначала вернуться к сохраненной позиции курсора, затем очистить экран от курсора до нижней части и, наконец, записать вывод.
Метод\033 не работал у меня. Метод \r работает, но на самом деле ничего не стирает, просто помещает курсор в начало строки. Поэтому, если новая строка короче старой, вы можете увидеть оставшийся текст в конце строки. В конце концов, tput был лучшим способом. У него есть другие возможности, помимо материала курсора, плюс он поставляется с предустановленной во многих дистрибутивах Linux и BSD, поэтому он должен быть доступен для большинства пользователей 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
Здесь немного обратного отсчета script, чтобы играть с:
#!/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"
Используйте символ возврата каретки:
echo -e "Foo\rBar" # Will print "Bar"
В случае, если выход прогресса является многострочным, или script уже напечатал новый символ строки, вы можете перепрыгнуть строки с чем-то вроде:
printf "\033[5A"
который заставит курсор прыгать на 5 строк вверх. Затем вы можете перезаписать все, что вам нужно.
Если это не сработает, вы можете попробовать printf "\e[5A"
или echo -e "\033[5A"
, который должен иметь тот же эффект.
В принципе, с escape-последовательностями вы можете контролировать почти все на экране.
Самый простой способ - использовать символ \r
, который я предполагаю.
Недостатком является то, что вы не можете иметь полные строки, поскольку он очищает только текущую строку.
Простой пример:
time=5
echo -n "Elapsed $time seconds"
sleep 10
time=15
echo -n "Elapsed $time seconds"
echo "\nDone"