Text-Processing

如何使用 echo 覆蓋標準輸出?

  • August 21, 2014

我們知道要覆蓋bar.txt,我們可以使用這個:

echo "foo" > bar.txt

但是我們怎樣才能覆蓋到標準輸出呢?我試過這個命令:

echo "foo" >

但它失敗了。我想要這個,因為我想列印這樣的東西:

Hello  

world

I'm 

HERE 

一次一個詞,我想刪除前一個詞(在標準輸出上一次一個詞)。

echo始終輸出到其標準輸出1。echo foo總是做一個write(1, "foo\n").

當您這樣做echo foo > file時,shell 會將echo命令的標準輸出更改為新file文件。echo foo然後仍然執行 awrite(1, "foo\n")但這次它的標準輸出(它的文件描述符 1)指向file,而不是它從 shell 繼承的標準輸出。

如果您想寫入標準輸出而不重定向標準輸出,只需編寫:

echo foo

如果您希望 stdout 指向的資源在 each 之前重新打開(並截斷)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是在標準輸出上打開的文件的符號連結。所以再次打開它>會截斷它(在其他 Unices 上,> /dev/fd/n就像dup2(n,1)它不會截斷文件一樣)。但是,如果 stdout 進入套接字,那將不起作用。

否則,您可以呼叫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 因為\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例如寫入FOOprints stderr。使用echo和在 Bourne-like shell 中,您可以echo >&2 FOO實現相同的結果。echo仍在寫入其標準輸出,但已使用>&2shell 重定向運算符將其標準輸出複制為 shell 的標準錯誤

引用自:https://unix.stackexchange.com/questions/151367