如何使用 echo 覆盖标准输出?

如何使用 echo 覆盖标准输出?

我们知道要覆盖bar.txt,我们可以使用这个:

echo "foo" > bar.txt

但我们如何覆盖标准输出呢?我尝试了这个命令:

echo "foo" >

但它失败了。我想要这个是因为我想打印这样的东西:

Hello  

world

I'm 

HERE 

一次一个单词,我想删除前一个单词(标准输出上一次一个单词)。

答案1

echo始终输出到其标准输出1echo foo总是做一个write(1, "foo\n").

当您执行此操作时echo foo > file,shell 会将echo命令的标准输出更改为新file文件。echo foothen 仍然执行 awrite(1, "foo\n")但这次它的 stdout (其文件描述符 1)指向file,而不是它从 shell 继承的 stdout。

如果您想写入标准输出而不需要该标准输出重定向, 写吧:

echo foo

如果您希望 stdout 指向的资源在每个之前重新打开(并截断)echo,那么这就更棘手了。

在 Linux(且仅限 Linux)上,您可以执行以下操作:

echo foo > /dev/fd/1
echo bar > /dev/fd/1
# now the file stdout points to (if it's a regular file) contains "bar"

在 Linux 上,/dev/fd/1是指向在 stdout 上打开的文件的符号链接。因此再次打开它>会截断它(在其他 Unices 上,> /dev/fd/n就像dup2(n,1)这样它不会截断文件)。如果标准输出连接到套接字,那将不起作用。

否则,您可以调用ftruncate()stdout (fd 1) 来截断它:

perl -e 'truncate STDOUT,0'
echo foo
perl -e 'truncate STDOUT,0'
echo bar

相反,如果你想要这些词,当 stdout 是终端时要在屏幕上相互覆盖,可以使用终端控制字符来影响光标定位。

 printf %s FOO
 printf '\r%s' BAR

BAR 将会覆盖 FOO,因为 FOO\r是指示终端将光标移动到行首的控制字符。

如果你这样做:

printf %s FOOBAR
printf '\r%s' BAZ

但是,您会BAZBAR在屏幕上看到。您可能需要使用另一个控制序列来清除线路。虽然\r回车是通用的,但清除屏幕的控制序列因终端而异。最好的方法是查询 terminfo 数据库来tput找到它:

clr_eol=$(tput el)
printf %s FOOBAR
printf '\r%s%s' "$clr_eol" BAZ

1如果使用 Korn 或 Z shell,另一个支持写入其他文件描述符的输出命令是printprint -u2 FOO例如写入FOO' prints stderr。使用echo类似 Bourne 的 shell,您可以echo >&2 FOO达到相同的结果。echo仍在写入其标准输出,但已使用 shell>&2重定向运算符将其标准输出复制为 shell 的 stderr

答案2

你可以说,

$clear && printf "before" && sleep 1 && clear && printf "after\n"

为了你的世界,

$clear && printf "Hello" && sleep 1 && clear && printf "World" && sleep 1 && clear && printf "I'm" && sleep 1 && clear && printf "Here\n"

答案3

如果您无论如何都要打印到终端,您可能只想省略换行符 ( -n) 并使用显式回车符:

echo -en 'hello, dear\r'; sleep 5; echo -en 'world\r'; echo

(请注意,您需要用空格填充字符串以完全覆盖它们。)

答案4

如果您想使用echo代替 Suchhi 的解决方案printf,请查看-eecho命令的选项。这允许您使用某些转义序列,包括\b退格键。与-n抑制换行符的选项一起,您可以执行以下操作:

 echo -n "Hello" && sleep 10 && echo -n -e "\b\b\b\b\bworld"

相关内容