Перезаписать последнюю строку в терминале
Мой bash - script выглядит следующим образом:
echo "Description:"
while [ $finishInput -eq 0 ]; do
read tmp
desc="$desc"$'\n'"$tmp"
if [ -z "$tmp" ]; then
finishInput="1"
fi
done
echo -n "Maintainer:"
read maintainer
Он читает desc var до тех пор, пока не будет пуста. После этого я хочу читать другие вещи.
При выполнении текущего текущего script он выглядит так:
Description:
Line 1
Line 2
Maintainer:
Я хотел бы перезаписать последнюю пустую строку с помощью "Maintainer:".
Я искал решение, но нашел только предложения, похожие на
echo -n "Old line"
echo -e "\r new line"
который остается на линии и перезаписывает его. Это невозможно в моем случае.
Ответы
Ответ 1
Просто используйте "\e[1A"
.
В вашем примере вы удаляете текст в той же строке:
$ echo -n "Old line"; echo -e "\e[0K\r new line"
new line
Если вы хотите вернуться к предыдущей строке, используйте \e [1A:
$ echo "Old line"; echo -en "\e[1A"; echo -e "\e[0K\r new line"
new line
Если вы хотите перейти на N строк вверх, используйте \e[<N>A
.
Ответ 2
Я построил функцию из Комментарий Денниса Уильямсона:
function clearLastLine() {
tput cuu 1 && tput el
}
Благодаря Деннису Уильямсону
Ответ 3
Нашел отличное руководство по escape-последовательностям и хотел бы подробнее остановиться на некоторых обсуждениях здесь.
Когда вы пишете в терминал, вы перемещаете невидимый курсор, как и в любом текстовом редакторе. При использовании echo
, он автоматически заканчивает вывод символом новой строки, который перемещает курсор на следующую строку.
$ echo "Hello" && echo " World"
Hello
World
Вы можете использовать -n
чтобы запретить новую строку, и если после этого вы повторите эхо, он добавит его в конец этой строки.
$ echo -n "Hello" && echo " World"
Hello World
Курсор остается там, где он был, поэтому сам по себе мы не можем использовать -n
для перезаписи предыдущей строки, нам нужно переместить курсор влево. Для этого нам нужно дать ему escape-последовательность, которую мы дадим echo
знать, что мы будем использовать с -e
а затем переместим курсор, предоставив возвратную каретку \r
которая помещает курсор в начало строки.
$ echo -n "Hello" && echo -e "\rWorld"
World
Может показаться, что это сработало, но посмотрим, что происходит с
$ echo -n "A longer sentance" && echo -e "\rShort sentance"
Short sentancence
Видишь лишних персонажей? Простое написание над строкой только меняет символы, где мы их написали.
Чтобы исправить это, принятый ответ выше использует escape-символ \e[0K
чтобы стереть все после курсора, после того, как курсор переместился влево. то есть \r
перейти к началу \e[0K
стереть до конца.
$ echo -n "A longer sentance" && echo -e "\r\e[0KShort sentance"
Short sentance
Важно \e
для начала escape-последовательности работает в zsh
но не в sh
и не обязательно в bash
, однако \033
работает во всех из них. Если вы хотите, чтобы ваш скрипт работал где угодно, вы должны указать \033
$ echo -n "A longer sentance" && echo -e "\r\033[0KShort sentance"
Short sentance
Но экранирующие символы могут предоставить еще больше полезности. Например, \033[1A
перемещает курсор на предыдущую строку, поэтому нам не нужен -n
в предыдущем эхо:
$ echo "A longer sentance" && echo -e "\r\033[1A\033[0KShort sentance"
Short sentance
\r
перейти к началу \033[1A
перейти вверх \033[0K
стереть до конца
Наконец, все это немного запутано в моей книге, так что вы можете превратить это в функцию:
overwrite() { echo -e "\r\033[1A\033[[email protected]"; }
Использование [email protected]
просто помещает все параметры функции в строку
$ echo Longer sentance && overwrite Short sentence
Short sentence
Надеюсь, что это помогает людям, которые хотят знать немного больше.
Ответ 4
Если вы echo -n "Something"
эхо без символа новой строки echo -n "Something"
, вы можете использовать \r
со своим следующим эхом, чтобы переместить "курсор" в начало строки echo -e "\\rOverwrite something"
.
![bash overwrite terminal line]()
#!/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"
Просто знайте, что если ваша новая строка короче вашей старой строки, хвост вашей старой строки все равно будет виден. Обратите внимание, что done..
в GIF выше.
Ответ 5
#!/bin/bash
echo "Description:"
while test -z $finishInput; do
read -s tmp
desc="$desc"$'\n'"$tmp"
if [ -z "$tmp" ]; then
finishInput=1
else
echo $tmp
fi
#echo "fi="$finishInput;
done
echo -n "Maintainer:"
read maintainer
Это решение избегает пустой строки, но вход не отражается до завершения строк.
Подсказка: моя версия bash не принимала "[$ finishInput -eq 0]".
Ответ 6
Если вы хотите запустить скрипт в цикле и не взорвать прокрутку, вы можете использовать следующий шаблон:
while sleep 10s; do
echo -n $(script)
echo -n -e "\e[0K\r"
done
Просто замените команду script
своей.