简体   繁体   English

Bash-如果第一个使用者失败,则在管道中重用输出

[英]Bash - reuse the output in pipes if the first consumer fails

I have an expensive operation ( curl call). 我的操作费用很高( curl调用)。 This may or may not produce JSON. 这可能会或可能不会产生JSON。 If it does, I want to pretty print it using json_pp . 如果是这样,我想使用json_pp漂亮地打印它。 But if that fails, I want to print it as-is. 但是,如果失败,我想按原样打印。

This is what I have now: 这就是我现在所拥有的:

filter "$ENVI" "$2" running | dns_ \
   | xargs  -L1 --max-args=1 -I{} $DEBUG_XARGS --no-run-if-empty \
   sh -c "echo 'Versions at {}': ; curl --fail http://... | json_pp"

The relevant part is 相关部分是

curl --fail http://... | json_pp

When the output is JSON, it's ok. 当输出为JSON时,就可以了。 But when it's not, I get: 但是当不是的时候,我得到:

malformed JSON string, neither array, object, number, string or atom, at character offset 0 (before "Version: 18.4.0, bui...") at /usr/bin/json_pp line 45. 格式错误的JSON字符串,数组,对象,数字,字符串或原子都不是,位于/ usr / bin / json_pp第45行的字符偏移量0(“ Version:18.4.0,bui ...”之前)。

I would like to somehow react to the error code of json_pp , so that if it is not 0 , the output would be passed further in the pipe (where cat would take it), but if it returned 0 (accepted the JSON), the pipe would not continue (or continue with json_pp 's output). 我想以某种方式对json_pp的错误代码做出反应,以便如果它不为0 ,则输出将在管道中进一步传递( cat将接收它的位置),但是如果它返回0 (接受JSON),则管道不会继续(或继续json_pp的输出)。

In other words, I want to skip the step in the pipe which fails. 换句话说,我想跳过失败的管道中的步骤。
How can I achieve this? 我该如何实现? Looking for something like 寻找类似的东西

curl --fail http://... | ifTheFollowingFailsThenPassAsIsOtherwiseUseOutputOf json_pp | cat

Because it all happens in xargs , I am looking for a short solution, something like tee . 因为这一切都发生在xargs ,所以我正在寻找一个简短的解决方案,例如tee It may be a Bash function, too. 它也可能是Bash函数。

tryOrCat() {
  local input output
  input=$(cat) || return
  if output=$("$@" <<<"$input"); then
    printf '%s\n' "$output"
  else
    printf '%s\n' "$input"
  fi
}

...thereafter: ...此后:

whatever | tryOrCat json_pp

Here's what I figured out a while after posting: 这是我发布后一段时间想出来的:

bbTmp=$(mktemp "${TMPDIR:-/tmp}/bbPp.XXXXXX")
export bbTmp # to be available to sh -c

filter "$ENVI" "$2" running | dns_ | xargs  -L1 --max-args=1 -I{} --no-run-if-empty \
  sh -c 'curl --fail http://{}/... | tee "$bbTmp" | json_pp 2>/dev/null || cat "$bbTmp"'

This works just as I need. 就像我需要的那样。 Thanks for the other tips, will be useful for more generic solutions. 感谢其他提示,对于更通用的解决方案将很有用。

Output in a pipeline can only be processed once. 管道中的输出只能处理一次。 You'll need to either duplicate it or save it. 您需要复制它或保存它。 The latter is easy: 后者很容易:

json=$(curl --fail http://...)
json_pp <<< "$json" || printf '%s\n' "$json"

This will leave json_pp 's error message visible. 这将使json_pp的错误消息可见。 If you want to hide it you can redirect stderr: 如果要隐藏它,可以重定向stderr:

json_pp <<< "$json" 2>/dev/null || printf '%s\n' "$json"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM