bash 在命令打印的每一行前添加文本

bash prepend text to every line printed by commands

我正试图找到一种方法来做这样的事情:

# script.sh:
cmd0
set_prepend "some text"
cmd1
cmd2
cmd3
unset_prepend
cmd4

然后无论 cmd1、2 和 3 生成什么标准输出,每一行都将以 "some text" 开头。命令之间没有任何关系,命令可以是任何命令(ls、cat、awk 等等):

$ script.sh
cmd0 line1
...
cmd0 lineN0
some text cmd1 line1
some text ...
some text cmd1 lineN1
some text cmd2 line1
some text ...
some text cmd2 lineN2
some text cmd3 line1
some text ...
some text cmd3 lineN3
cmd4 line1
...
cmd4 lineN4

我能想到的唯一方法远非优雅:

script.sh | prepender 

对于prepender接收到的每一行,它都会检查一个文件是否存在;如果文件存在,则内容是要添加的文本; set_prepend 将创建该文件,而 unset_prepend 将删除它。但是缓冲会干扰这一点,因此必须将其关闭,而且我不确定如何保证在执行下一个脚本 cmd 之前,prepender 会处理去往 stdout 的行(否则可能出现竞争条件)。

使用exec 将输出重定向到管道。您需要将旧的 stdout 保存在另一个 FD 中,以便稍后恢复。

set_prepend() {
    exec 3>&1 | sed "s/^/ /"
}
unset_prepend() {
    exec >&3 3>&-
}