【问题标题】:shell: send grep output to stderr and leave stdout intactshell:将 grep 输出发送到 stderr 并保持 stdout 不变
【发布时间】:2021-11-09 15:26:56
【问题描述】:

我有一个输出到stdout 的程序(实际上它输出到stderr,但我可以使用2>&1 等轻松地将其重定向到stdout

我想在程序的输出上运行grep,并将所有匹配项重定向到stderr,同时在stdout 上留下不匹配的行(或者,我很高兴得到所有行 - 不仅仅是无与伦比的 - 在stdout)

例如

$ myprogram() {
cat <<EOF
one line
a line with an error
another line
EOF
}
$ myprogram | greptostderr error >/dev/null
a line with an error
$ myprogram | greptostderr error 2>/dev/null
one line
another line
$

一个简单的解决方案是:

myprogram | tee logfile
grep error logfile 1>&2
rm logfile

但是,我宁愿在 stderr 出现匹配行时获取它们,而不是在程序退出时...

最后,我找到了this,这给了我一个类似这样的 POSIX 解决方案的提示:

greptostderr() {
  while read LINE; do
    echo $LINE
    echo $LINE | grep -- "$@" 1>&2
  done
}

无论出于何种原因,这不会输出任何内容(可能是缓冲问题)。

一个看起来有点难看但似乎可行的解决方案是这样的:

greptostderr() {
  while read LINE; do
    echo $LINE
    echo $LINE | grep -- "$@" | tee /dev/stderr >/dev/null
  done
}

有没有更好的方法来实现这一点?

理想情况下,我正在寻找一个 POSIX shell 解决方案,但 bash 也很好......

【问题讨论】:

    标签: bash redirect sh stdout stderr


    【解决方案1】:

    我会使用awk 而不是grep,这样可以更灵活地处理匹配和不匹配的行。

    myprogram | awk -v p=error '{ print > ($0 ~ p ? "/dev/stderr" : "/dev/stdout")}'
    

    每一行都会被打印出来; $0 ~ p 的结果确定该行是打印到标准错误还是标准输出。 (您可能需要根据您的文件系统调整输出文件名。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-01-21
      • 2018-07-01
      • 2019-03-29
      • 2011-10-19
      • 2015-07-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多