回车本身仅将光标移动到行首。如果每一个新的输出行至少和前一个一样长,那没关系,但如果新行较短,前一行不会被完全覆盖,例如:
$ echo -e "abcdefghijklmnopqrstuvwxyz\r0123456789"
0123456789klmnopqrstuvwxyz
要真正清除新文本的行,您可以在 \r
之后添加 \033[K
:
$ echo -e "abcdefghijklmnopqrstuvwxyz\r\033[K0123456789"
0123456789
http://en.wikipedia.org/wiki/ANSI_escape_code
用 \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
for i in {1..100000}; do echo -en "\r$i"; done
避免 seq 调用:-)
只要线路长度不超过终端宽度,Derek Veit 的答案就可以很好地工作。如果不是这种情况,以下代码将防止垃圾输出:
在第一次写这行之前,做
tput sc
保存当前光标位置。现在每当你想打印你的行时,使用
tput rc
tput ed
echo "your stuff here"
先回到保存的光标位置,然后从光标到底部清屏,最后写入输出。
tput sc # save cursor echo '' > sessions.log.json while [ 1 ]; do curl 'http://localhost/jolokia/read/*:type=Manager,*/activeSessions,maxActiveSessions' >> sessions.log.json echo '' >> sessions.log.json cat sessions.log.json | jq '.' tput rc;tput el # rc = restore cursor, el = erase to end of line sleep 1 done
tput ed
而不是 tput el
。 @Um 的示例使用了 ed
(也许他在您发表评论后修复了它)。
\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"
如果进度输出是多行的,或者脚本已经打印了换行符,您可以使用以下内容跳转行:
printf "\033[5A"
这将使光标向上跳 5 行。然后你可以覆盖你需要的任何东西。
如果这不起作用,您可以尝试 printf "\e[5A"
或 echo -e "\033[5A"
,它们应该具有相同的效果。
基本上,使用 escape sequences,您几乎可以控制屏幕上的所有内容。
tput cuu 5
,其中 5 是行数(cuu
向上移动,cud
向下移动)。
tput cuu 5
后如何清除(“重置”)行?
使用回车符:
echo -e "Foo\rBar" # Will print "Bar"
可以通过放置回车\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
如果您只想清除前一行,以下可能会解决问题。
printf '\033[1A\033[K'
对于多行,在循环中使用它:
for i in {1..10}; do
printf '\033[1A\033[K'
done
这将清除最后 10 行。
您可以使用 tput
,而不是在 echo
中使用反斜杠。为了简化这一点,您可以创建一个函数:
#!/bin/bash
function consoleoneline {
# Start process and save all outputs in a temporary directory
tput sc # save current cursor in console
local PIPE_DIRECTORY=$(mktemp -d)
trap "rm -rf '$PIPE_DIRECTORY'" EXIT
mkfifo "$PIPE_DIRECTORY/stdout"
mkfifo "$PIPE_DIRECTORY/stderr"
"$@" >"$PIPE_DIRECTORY/stdout" 2>"$PIPE_DIRECTORY/stderr" &
local CHILD_PID=$!
# Replace all outputs with a leading "›"
# `tput` allows to reset the cursor to the previous line
sed "s/^/`tput rc;tput el`› /" "$PIPE_DIRECTORY/stdout" &
sed "s/^/`tput rc;tput el`› /" "$PIPE_DIRECTORY/stderr" >&2 &
# Wait command has exited, remove temporary directory and reset cursor
wait "$CHILD_PID"
rm -rf "$PIPE_DIRECTORY"
tput ed
}
consoleoneline bash -c 'echo 1 && sleep 1 && echo 2 && sleep 1 && echo 3'
不定期副业成功案例分享
\e[K
而不是\033[K
。\033[K
之前执行\033[G
io\r
虽然显然\r
要简单得多。此外,invisible-island.net/xterm/ctlseqs/ctlseqs.html 提供了比 Wikipedia 更多的详细信息,并且来自 xterm 开发人员。