【问题标题】:Prepend then redirect前置然后重定向
【发布时间】:2020-03-02 06:57:37
【问题描述】:

我想将stderr 重定向到一个用于记录目的的文件:

2>> "$logFile"

如何将字符串 "error: " 添加到每一行?

【问题讨论】:

    标签: bash pipe io-redirection


    【解决方案1】:

    另一个选项是sed:

    2> >(sed -u 's/^/error: /' >> "$logfile")
    

    可能无法仅使用 bash 内置函数,因为这种为字符串添加前缀的机制需要与流一起使用。

    注意使用gnu sed 选项-u (--unbuffered) 从输入文件中加载最少量的数据并更频繁地刷新输出缓冲区。

    Code Demo

    【讨论】:

    • sed 和 awk 之间哪个效率更高?
    • 可能两者都会在相似的线路上执行,但我的猜测是它仍然比使用while 循环更有效
    • 通过在$logfile 中的每一行前加上"error: " 前缀,它在我的测试中确实有效
    • 可能相关:在 AIX 上,bash 使用 /tmp 目录中的临时文件,而不是 /def/fd
    【解决方案2】:

    您可以使用进程替换。

    2> >(awk '{print "error: " $0}' >> "$logfile")
    

    或者使用支持损坏进程替换的旧外壳:

    { { prog >&3; } 2>&1 | sed 's/^/error: /' >> "$logfile"; } 3>&1
    

    在这里,我们将prog 的标准输出保存到 fd 3,将其标准错误通过管道传输到 sed,最后将 fd 3 恢复到标准输出。

    【讨论】:

    • 是否可以在没有awk 的情况下仅使用 bash 内置函数来做到这一点?
    • 我想使用 exec 来做整个事情,这样它在我的所有脚本中都有效。如果我执行 exec >&3 我会收到错误“3:错误的文件描述符”
    【解决方案3】:

    纯 Bash 版本:

    2> >(while read -r line ; do echo "error: $line" ; done >> "$logFile")
    

    。 . .但请注意,如果程序写入任何空字节,或者程序没有在最后一行之后写入换行符,这将出现异常。 (这两个问题都是可以解决的,但在某些时候我们不得不质疑是否值得仅仅为了避免调用 awk 或 sed。)

    【讨论】:

      【解决方案4】:

      由于在我的 AIX 上使用 Bash 4.2.50 进行进程替换存在问题,https://en.wikipedia.org/wiki/Process_substitution 的替代方法是使用 FIFO:

      logFile='/tmp/stderr.log'
      fifoFile='/tmp/log123.fifo'
      mkfifo $fifoFile
      glub 2>> $fifoFile & #the & is needed because otherwise the FIFO will block
      cat $fifoFile | sed -u 's/^/error: /' >> "$logFile"
      

      Code demo

      第三行的和号& 是必需的,否则FIFO 将阻塞,直到有读取器为止。

      另一种选择是在执行期间不添加任何内容,等到日志记录完成后再处理日志文件。

      【讨论】:

      • 真的需要fifo吗?我认为{ { glub >&3; } 2>&1 | sed 's/^/error: /' >> "$logfile"; } 3>&1 也应该可以正常工作
      • @oguzismail 谢谢,我觉得不错!你为什么不把这个作为答案发布?还要添加一些解释如何?我不确定我是否理解所有大括号的原因以及重定向到底发生了什么,尤其是到 fd 3。
      • @oguzismail 你怎么能用 exec 重写你的重定向,以便它们在整个脚本中有效?
      • 用这个和简短的解释更新了我的答案。 Wrt 你怎么能用 exec 重写你的重定向,我不明白这部分
      猜你喜欢
      • 1970-01-01
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      相关资源
      最近更新 更多