bash 覆盖终端上的最后一行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11283625/
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
Overwrite last line on terminal
提问by Zulakis
My bash-script looks as following:
我的 bash 脚本如下所示:
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
It reads to the desc var until a empty line is passed. After that, i want to read in other stuff.
它读取 desc var,直到传递一个空行。在那之后,我想阅读其他东西。
When executing my current script it looks like this:
执行我当前的脚本时,它看起来像这样:
Description:
Line 1
Line 2
Maintainer:
I would like to overwrite the last empty line with the "Maintainer:".
我想用“Maintainer:”覆盖最后一个空行。
I searched for a solution but only found suggestions which were like
我搜索了一个解决方案,但只找到了类似的建议
echo -n "Old line"
echo -e "\r new line"
which stays on the line and overwrites it. This is not possible in my case.
它保持在线并覆盖它。在我的情况下这是不可能的。
回答by Igor Chubin
Just use "\e[1A"
.
只需使用"\e[1A"
.
In your example you delete the text at the same line:
在您的示例中,您删除了同一行的文本:
$ echo -n "Old line"; echo -e "\e[0K\r new line"
new line
When you want to return to the previous line use \e[1A:
当您想返回到上一行时,请使用 \e[1A:
$ echo "Old line"; echo -en "\e[1A"; echo -e "\e[0K\r new line"
new line
When you want to go N lines up, use \e[<N>A
.
当您想排 N 行时,请使用\e[<N>A
.
回答by DanielM
Found a great guide on escape sequencesand wanted to expand on some of the discussions here.
找到了一个很好的转义序列指南,并希望扩展这里的一些讨论。
When you write out to a terminal, you move an invisible cursor around, much like you do when you write in any text editor. When using echo
, it will automatically end the output with a new line character which moves the cursor to the next line.
当你写到终端时,你移动了一个不可见的光标,就像你在任何文本编辑器中写的一样。使用时echo
,它会自动以换行符结束输出,将光标移动到下一行。
$ echo "Hello" && echo " World"
Hello
World
You can use -n
to prevent the new line and if you echo again after this, it will append it to the end of that line
您可以使用-n
来阻止新行,如果您在此之后再次回显,它会将其附加到该行的末尾
$ echo -n "Hello" && echo " World"
Hello World
The cursor remains where it was so, on it's own, we can't use -n
to overwrite the previous line, we need to move the cursor to the left. To do that we need to give it an escape sequence, which we let echo
know we're going to use with -e
and then move the cursor by providing a return carriage \r
which puts the cursor at the beginning of the line.
光标保持原样,靠它自己,我们不能-n
用来覆盖上一行,我们需要将光标向左移动。要做到这一点,我们需要给它一个转义序列,让我们echo
知道我们将使用它-e
,然后通过提供一个\r
将光标放在行首的回车来移动光标。
$ echo -n "Hello" && echo -e "\rWorld"
World
That may look like it worked, but see what happens with
这可能看起来有效,但看看会发生什么
$ echo -n "A longer sentance" && echo -e "\rShort sentance"
Short sentancence
See the extra characters? Simply writing over the line only changes the characters where we wrote them.
看到额外的字符了吗?简单地写在行上只会改变我们写的字符。
To fix this, the accepted answer above uses the escape character \e[0K
to erase everything after the cursor, after the cursor has moved left. i.e. \r
move to beginning \e[0K
erase to end.
为了解决这个问题\e[0K
,在光标向左移动后,上面接受的答案使用转义字符擦除光标后的所有内容。即\r
移动到开始\e[0K
擦除结束。
$ echo -n "A longer sentance" && echo -e "\r\e[0KShort sentance"
Short sentance
Important\e
to begin escape sequences works in zsh
but not in sh
and not necessarily in bash
, however \033
works in all of them. If you want your script to work anywhere, you should preference \033
重要的\e
是开始转义序列适用于zsh
但不适用,sh
不一定适用于bash
,但\033
适用于所有这些。如果你想让你的脚本在任何地方工作,你应该优先\033
$ echo -n "A longer sentance" && echo -e "\r3[0KShort sentance"
Short sentance
But escape characters can provide even more utility. For example \033[1A
moves the cursor to the previous line so we don't need the -n
on the previous echo:
但是转义字符可以提供更多的实用性。例如\033[1A
将光标移动到上一行,这样我们就不需要-n
上一个回显:
$ echo "A longer sentance" && echo -e "\r3[1A3[0KShort sentance"
Short sentance
\r
move to the beginning \033[1A
move up \033[0K
erase to the end
\r
移到开头\033[1A
向上移\033[0K
擦除到结尾
Finally, this is all a bit messy in my book, so you can turn this into a function:
最后,这在我的书中有点乱,所以你可以把它变成一个函数:
overwrite() { echo -e "\r3[1A3[0K$@"; }
Using $@
just puts all the parameters of the function into the string
使用$@
只是将函数的所有参数放入字符串中
$ echo Longer sentance && overwrite Short sentence
Short sentence
Hope that helps people who want to know a bit more.
希望对想多了解的人有所帮助。
回答by Murmel
I built a function from Dennis Williamsons Comment:
我从Dennis Williamsons 评论中构建了一个函数:
function clearLastLine() {
tput cuu 1 && tput el
}
Thanks to Dennis Williamson
感谢丹尼斯威廉姆森
回答by Derek Soike
If you echo without the newline character echo -n "Something"
, you can use \r
with your next echo to move the 'cursor' to the beginning of the line echo -e "\\rOverwrite something"
.
如果您在没有换行符的情况下回显echo -n "Something"
,您可以使用\r
下一个回显将“光标”移动到行的开头echo -e "\\rOverwrite something"
。
#!/bin/bash
CHECK_MARK="3[0;32m\xE2\x9C\x943[0m"
echo -e "\n\e[4mDoing Things\e[0m"
echo -n "doing thing 1..."
sleep 1
echo -e "\r${CHECK_MARK} thing 1 done"
Just be aware that if your new string is shorter that your old string, the tail of your old string will still be visible. Note the done..
in the gif above.
请注意,如果您的新字符串比旧字符串短,则旧字符串的尾部仍然可见。请注意done..
上面 gif 中的内容。
回答by Michael Besteck
#!/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
This solution avoids the empty line, but input is not echoed before the lines are complete.
此解决方案避免了空行,但在行完成之前不会回显输入。
Hint: My version of bash did not accept "[ $finishInput -eq 0 ]".
提示:我的 bash 版本不接受“[ $finishInput -eq 0 ]”。
回答by maxywb
If you want to run a script in a loop and not blow up your scrollback, you can use the following pattern:
如果您想在循环中运行脚本并且不破坏回滚,则可以使用以下模式:
while sleep 10s; do
echo -n $(script)
echo -n -e "\e[0K\r"
done
Just replace the script
command with your own.
只需script
用您自己的命令替换命令即可。