Как удалить и заменить последнюю строку в терминале с помощью bash?

Я хочу реализовать индикатор выполнения, показывающий прошедшие секунды в bash. Для этого мне нужно стереть последнюю строку, показанную на экране (команда «очистить» стирает весь экран, но мне нужно стереть только строку индикатора выполнения и заменить ее новой информацией).

Окончательный результат должен выглядеть следующим образом:

$ Elapsed time 5 seconds

Затем через 10 секунд я хочу заменить это предложение (в той же позиции на экране) на:

$ Elapsed time 15 seconds
79 голосов | спросил Debugger 5 MarpmFri, 05 Mar 2010 19:06:42 +03002010-03-05T19:06:42+03:0007 2010, 19:06:42

8 ответов


0

повторить возврат каретки с \ 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
ответил Ken 5 MarpmFri, 05 Mar 2010 19:08:38 +03002010-03-05T19:08:38+03:0007 2010, 19:08:38
0

Возврат каретки сам по себе только перемещает курсор в начало строки. Это нормально, если каждая новая строка вывода имеет длину по меньшей мере такую ​​же, как и предыдущая, но если новая строка короче, предыдущая строка не будет полностью перезаписана, например:

$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz

Чтобы действительно очистить строку для нового текста, вы можете добавить \033[K после \r:

$ echo -e "abcdefghijklmnopqrstuvwxyz\r\033[K0123456789"
0123456789

http://en.wikipedia.org/wiki/ANSI_escape_code

ответил Derek Veit 21 J000000Thursday11 2011, 14:06:36
0

Ответ Дерека Вейта работает хорошо, если длина линии никогда не превышает ширину терминала. Если это не так, следующий код предотвратит вывод нежелательной почты:

прежде чем строка будет написана в первый раз, сделайте

tput sc

, которая сохраняет текущую позицию курсора. Теперь, когда вы хотите напечатать свою строку, используйте

tput rc
tput ed
echo "your stuff here"

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

ответил Um. 20 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 20 Sep 2013 16:04:48 +0400 2013, 16:04:48
0

Метод \ 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

Вот небольшой скрипт обратного отсчета для игры:

#!/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"
ответил lee8oi 14 Jpm1000000pmWed, 14 Jan 2015 23:45:22 +030015 2015, 23:45:22
0

Используйте символ возврата каретки:

echo -e "Foo\rBar" # Will print "Bar"
ответил Mikael S 5 MarpmFri, 05 Mar 2010 19:09:25 +03002010-03-05T19:09:25+03:0007 2010, 19:09:25
0

Если результат выполнения многострочный, или сценарий уже напечатал символ новой строки, вы можете перейти к следующей строке:

printf "\033[5A"

, который заставит курсор подскочить на 5 строк. Затем вы можете перезаписать все, что вам нужно.

Если это не сработает, попробуйте printf "\e[5A" или echo -e "\033[5A", который должен иметь тот же эффект.

Как правило, с помощью escape-последовательностей вы можете управлять почти все на экране.

ответил Mr. Goferito 20 Mayam17 2017, 01:16:12
0

Этого можно добиться, поместив возврат каретки \r.

В единственной строке кода с printf

for i in {10..1}; do printf "Counting down: $i\r" && sleep 1; done

или с помощью echo -ne

for i in {10..1}; do echo -ne "Counting down: $i\r" && sleep 1; done
ответил Akif 27 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 27 Sep 2018 07:59:57 +0300 2018, 07:59:57
0

Самым простым способом является использование символа \r.

Недостаток в том, что у вас не может быть завершенных строк, так как он очищает только текущую строку.

Простой пример:

time=5
echo -n "Elapsed $time seconds"
sleep 10
time=15
echo -n "Elapsed $time seconds"

echo "\nDone"
ответил Romuald Brunet 5 MarpmFri, 05 Mar 2010 19:13:01 +03002010-03-05T19:13:01+03:0007 2010, 19:13:01

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132