【问题标题】:Test if the input stream not empty without consuming data from it在不消耗数据的情况下测试输入流是否为空
【发布时间】:2021-08-19 09:16:29
【问题描述】:

考虑下一个 sn-p。

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

【问题讨论】:

  • 这不是一个 bash 问题,而是一个概念问题。你不能做这个。假设您进行了这样的测试并确定输入流为空。 .0007ns 之后,流中可能有数据,因此您的测试毫无意义。
  • 我可以测试 EOF。在 C/C++ 中,我可以肯定。所以可能有一个工具可以完成这项工作,不是吗?
  • 代码中的$(cat) 是否试图处理generate_build_specs 的未过滤(通过awk)输出?
  • feof() 不是这样工作的。完全没有。 feof 仅告诉您读取操作是否由于错误或到达文件末尾而返回 EOF。你可以getchar,然后ungetc,但这并不是不读就确定文件中是否有数据;它正在显式读取一个字节(该字节现在对任何其他读取器都不可用)。
  • @kyb,您可以poll fd 并检查是否在revents 中设置了 POLLNVAL。

标签: bash shell grep cat


【解决方案1】:

您无需深入了解流。只需将输出存储在变量中即可。

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 次。

【讨论】:

【解决方案2】:

不完全是您要求的,但对于您的情况,功能等效:

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 的预期输出如何,我不能说这种方法是否适用于您的情况。

【讨论】:

  • 字符串macos可能会在发布前后出现。顺序无关紧要
  • 正如你所见,我只想在流中有数据时才写消息,如果没有,则不要回显。
  • 更新了我的答案。现在,macos 和 release 必须在某行中以任意顺序发生;否则会显示错误消息。作为旁注:也许将错误消息写入标准错误而不是标准输出是有意义的......
  • 感谢您的努力。但我需要在错误消息中显示删除的构建规范。正如我所说的那样。
  • 在这种情况下,您必须将输入存储到变量中并决定变量的内容。
【解决方案3】:

在讨论中,我意识到

如果不从流中读取至少一个字符,就无法检查流是否结束。

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

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

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

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

sed -zE 's,^.+$,::ERROR:: \0\n,'

这意味着只有在输入不为空时才添加字符串并输出。正则表达式^.+$ 检查是否至少有一个符号。但我认为作为所有单行者,这一个更难阅读。

感谢大家的参与。

【讨论】:

    猜你喜欢
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多