测试输入流是否不为空而不从中消耗数据

Test if the input stream not empty without consuming data from it

考虑下一个片段。

generate_build_specs(){
  echo ubuntu gcc9 debug
  echo macos clang debug
  echo macos gcc10 release
  echo macos clang release
}
generate_build_specs | awk -v IGNORECASE=1 '/macos/ && /release/' |
  if input_data_available ;then
      echo "FIXME. Cannot build 'macos release' until it is fixed. Buildspec dropped: $(cat)"
  fi

我的想法是仅当流中的数据可用时才使用输入流的内容回显消息。流中有类似 peek(char) 的内容,而不是从那里获取。

当然,我知道一个解决方法。即

var="$(cat)"; if test -n "$var"; echo "blah:: $var" ; fi

不完全符合您的要求,但对于您的案例来说功能相当:

if generate_build_specs | awk -v IGNORECASE=1 '/macos/ && /release/' | grep -q .
then
  echo No data produced
fi

如果我们挑剔的话,我们应该指出,如果管道产生的数据只包含空行,这也会导致没有产生数据

如果您确实拥有您发布的那个 awk 命令(并且没有在此处显示简化版本来解释您的观点),您也许还可以编写

if generate_build_specs | grep -i macos | grep -iqv 'release'
then
  ..echo "No data produced which contains the strings 'macos' and 'release'"
fi

这意味着字符串 macos 必须比字符串 release 在一行中出现得更早。因为我不知道 generate_builds_specs 的预期输出是什么样子,所以我不能说这种方法是否适用于你的情况。

你不需要去流。只需将输出存储在一个变量中。

buildspec=$(generate_build_specs | awk -v IGNORECASE=1 '/macos/ && /release/')
if [[ -n "${buildspec}" ]]; then
   printf "%s\n" "FIXME. Cannot build 'macos release' until it is fixed." \
        "Buildspec dropped:" "${buildspec}"
fi

我使用 printf 在您可能需要的地方获取换行符,您也可以使用 echo 3 次。

在讨论中,我意识到

there is no way to check if a stream is ended without reading at least one char from it.

input_data_available 无法在 Bash 中实施。这是一个关于流的概念问题。

所以目前的解决方案是将输入存储到变量中,然后对其进行处理。

var="$(cat)"; if test -n "$var"; then echo "::ERROR:: $var" ; fi

更好的(即简洁的)方法是:

sed -zE 's,^.+$,::ERROR:: [=11=]\n,'

表示前置字符串,仅当输入不为空时才输出。 Regexp ^.+$ 检查是否至少有一个符号。但是我觉得和所有的单行本一样,这个更难读。

谢谢大家的参与