bash 如何使用bash删除和替换终端中的最后一行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2388090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 19:00:29  来源:igfitidea点击:

How to delete and replace last line in the terminal using bash?

bashreplaceterminalline

提问by Debugger

I want to implement a progress bar showing elapsed seconds in bash. For this, I need to erase the last line shown on the screen (command "clear" erases all the screen, but I need to erase only the line of the progress bar and replace it with the new information).

我想在 bash 中实现一个显示经过秒数的进度条。为此,我需要擦除屏幕上显示的最后一行(命令“清除”会擦除所有屏幕,但我只需要擦除进度条的行并将其替换为新信息)。

Final result should look like:

最终结果应如下所示:

$ Elapsed time 5 seconds

Then after 10 seconds i want to replace this sentence (in the same position in the screen) by:

然后 10 秒后,我想将这句话(在屏幕中的相同位置)替换为:

$ Elapsed time 15 seconds

回答by Derek Veit

The carriage return by itself only moves the cursor to the beginning of the line. That's OK if each new line of output is at least as long as the previous one, but if the new line is shorter, the previous line will not be completely overwritten, e.g.:

回车本身只会将光标移动到行首。如果每一行新输出至少与前一行一样长,那没关系,但如果新行更短,则前一行不会被完全覆盖,例如:

$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz

To actually clear the line for the new text, you can add \033[Kafter the \r:

要实际清除新文本的行,您可以在\033[K之后添加\r

$ echo -e "abcdefghijklmnopqrstuvwxyz\r3[K0123456789"
0123456789

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

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

回答by Ken

echo a carriage return with \r

用 \r 回显回车

seq 1 1000000 | while read i; do echo -en "\r$i"; done

from man echo:

从人回声:

-n     do not output the trailing newline
-e     enable interpretation of backslash escapes

\r     carriage return

回答by Um.

Derek Veit's answer works well as long as the line length never exceeds the terminal width. If this is not the case, the following code will prevent junk output:

只要线路长度从不超过终端宽度,Derek Veit 的答案就可以很好地工作。如果不是这种情况,以下代码将防止垃圾输出:

before the line is written for the first time, do

在第一次写这行之前,做

tput sc

which saves the current cursor position. Now whenever you want to print your line, use

保存当前光标位置。现在,每当您想打印线条时,请使用

tput rc
tput ed
echo "your stuff here"

to first return to the saved cursor position, then clear the screen from cursor to bottom, and finally write the output.

先返回到保存的光标位置,然后从光标到底部清屏,最后写入输出。

回答by lee8oi

The \033 method didn't work for me. The \r method works but it doesn't actually erase anything, just puts the cursor at the beginning of the line. So if the new string is shorter than the old one you can see the leftover text at the end of the line. In the end tput was the best way to go. It has other uses besides the cursor stuff plus it comes pre-installed in many Linux & BSD distros so it should be available for most bash users.

\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

Here's a little countdown script to play with:

这是一个可以玩的倒计时小脚本:

#!/bin/bash
timeout () {
    tput sc
    time=; while [ $time -ge 0 ]; do
        tput rc; tput el
        printf "" $time
        ((time--))
        sleep 1
    done
    tput rc; tput ed;
}

timeout 10 "Self-destructing in %s"

回答by Mr. Goferito

In case the progress output is multi line, or the script would have already printed the new line character, you can jump lines up with something like:

如果进度输出是多行,或者脚本已经打印了换行符,您可以使用以下内容跳行:

printf "\033[5A"

printf "\033[5A"

which will make the cursor to jump 5 lines up. Then you can overwrite whatever you need.

这将使光标向上跳 5 行。然后你可以覆盖任何你需要的东西。

If that wouldn't work you could try printf "\e[5A"or echo -e "\033[5A", which should have the same effect.

如果这不起作用,您可以尝试printf "\e[5A"echo -e "\033[5A",这应该具有相同的效果。

Basically, with escape sequencesyou can control almost everything in the screen.

基本上,使用转义序列,您几乎可以控制屏幕中的所有内容。

回答by Mikael S

Use the carriage return character:

使用回车符:

echo -e "Foo\rBar" # Will print "Bar"

回答by Akif

Can achieve it by placing carriage return \r.

可以通过放置回车来实现\r

In a single line of code with printf

在一行代码中 printf

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

or with echo -ne

或与 echo -ne

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