【问题标题】:Prefix for command output命令输出前缀
【发布时间】:2018-03-27 08:02:15
【问题描述】:

this question我学会了如何为命令的每个输出添加前缀:

command | sed "s/^/[prefix] /"

但这只会为stdout 中的每一行添加前缀。
我成功地使用以下方法将前缀也添加到stderr 输出。

command 2>&1 | sed "s/^/[prefix] /"

但这只会将结果发送给stdout

如何在将行推送到前一个输出时为command 的任何输出添加前缀(同时保留stdout 和stderr)?

【问题讨论】:

  • 为什么不以类似的方式重定向? command 2>&1 | sed "s/^/[prefix] /" 1>&2 ??您将stderr 重定向到stdout,然后通过管道传输到sed,然后如果您想在stderr 上发出该输出,则将stdout 重定向到stderr。每个管道只是将第一个进程的stdout 指向下一个进程的stdin。如果您希望在stderr 上获得最终输出,则必须将最终的stdout 重定向到stderr
  • 然后我将一切都发送到标准错误。我想保留标准输出和标准错误
  • 如果你想在stdout 上输出信息,那么你什么都不用做,这是默认的输出流。只有当您需要更改它时才会重定向。

标签: bash command-line stdout stderr


【解决方案1】:

结合 iBug 的回答和 thisespecially this 的回答,我想出了一个使用临时文件描述符的单行:

command 1> >(sed "s/^/[prefix]/") 2> >(sed "s/^/[prefix]/" >&2)

或者作为一个函数:

function prefix_cmd {
    local PREF="${1//\//\\/}" # replace / with \/
    shift
    local CMD=("$@")
    ${CMD[@]} 1> >(sed "s/^/${PREF}/") 2> >(sed "s/^/${PREF}/" 1>&2)
}
prefix_cmd "prefix" command

【讨论】:

  • 请注意,当您在函数中使用新变量时,通常最好将它们设为local。这样,您就不会破坏预先存在的变量 $PREF$CMD,以防您在脚本的其他地方使用这些名称。
【解决方案2】:

您只能使用 shell 管道语法来管道标准输出。如果要分别处理 stdout 和 stderr,则需要两个管道。命名管道可以在这里工作。

这是一个演示解决方案的示例脚本

#!/bin/bash

PREF="$1"
shift

NPOUT=pipe.out
NPERR=pipe.err
mkfifo $NPOUT $NPERR

# Make two background sed processes
sed "s/^/$PREF/" <$NPOUT &
sed "s/^/$PREF/" <$NPERR >&2 &

# Run the program
"$@" >$NPOUT 2>$NPERR
rm $NPOUT $NPERR

用法:

./foo.sh "[prefix] " command -options

它将向command 提供其标准输入并将command 的标准输出和标准错误分别发送到其标准输出和标准错误。

注意我没有抑制sed 的标准错误,这可能会干扰输出。你可以这样做:

sed "s/^/$PREF/" <$NPOUT 2>/dev/null &
                         ^^^^^^^^^^^

【讨论】:

  • 如何避免[1] 1178 [2] 1179 ... [1]- Done sed "s/^/$PREF/" &lt; $NPOUT [2]+ Done sed "s/^/$PREF/" &lt; $NPERR 1&gt;&amp;2 ?
  • 这个解决方案很好,因为除了 $CMD 数组之外,它还符合 POSIX(因此是可移植的)。您有什么理由需要以这种方式使用$CMD$@ 一个人就够了吗?
  • @RoVo 如果您在脚本中运行,这些不应该弹出。它由 Bash 生成,仅在交互模式下出现。
猜你喜欢
  • 1970-01-01
  • 2018-01-03
  • 2021-02-07
  • 2020-08-26
  • 1970-01-01
  • 2021-09-10
  • 2014-12-11
  • 1970-01-01
  • 2019-11-09
相关资源
最近更新 更多