【问题标题】:How to capture stderr in a variable and pipe stdout through如何在变量中捕获标准错误并通过管道传输标准输出
【发布时间】:2016-04-21 09:38:54
【问题描述】:

我正在尝试将 curl 响应的标头(来自 stderr)存储在一个变量中,并将正文(来自 stdout)通过管道传输到 grep。

这是我目前的尝试:

{
  HEADERS=$(curl -vs $URL 2>&1 1>&3-)
  echo "$HEADERS"
} 3>&1 | grep "regex" >> filename
echo "$HEADERS"

当我使用bash -x script.sh 运行脚本时,我看到+ HEADERS='...' 具有预期的输出,但我无法使用$HEADERS"$HEADERS" 在内联组内外访问它们。

身体按预期通过管道。

【问题讨论】:

  • 所以您希望grep 输出在终端或其他地方?
  • curl -vs -$URL 2>&1 1>&3-curl -vs $URL 2>&1 1>&3-
  • 有什么理由不只是将 header 设置为变量,然后 grep 变量而不是这个复杂的管道?
  • @anishsane 在这种情况下,grep 输出应附加到filename。这部分有效。
  • @123 该变量包含来自 stderr 的标头。 grep 处理来自标准输出的正文。

标签: bash shell curl stderr


【解决方案1】:

作为anubhava 正确diagnosed,问题在于您将HEADERS 设置在子进程中,而不是在shell 的主进程中。

您可以使用 Bash 的 process substitution 来避免该问题,而无需使用在 shell 中断时必须清理的临时文件:

HEADERS=""
{ HEADERS=$(curl -vs "$URL" 2>&1 1>&3-); } 3> >(grep "regex" > file)
echo "$HEADERS"

grep 子进程被进程替换隐藏。 3>>(…) 之间的空格是必需的。

【讨论】:

    【解决方案2】:

    您丢失了HEADERS 变量,因为使用了在子 shell 中分叉和运行管道命令的管道,而父 shell 看不到在子 shell 中创建的变量。

    您可以通过临时文件执行此操作:

    { f=$(mktemp /tmp/curl.XXXXXX); curl -vs "$URL" 2>"$f" |
    grep 'regex' >> filename; HEADERS="$(<$f)"; trap 'rm -f "$f"' EXIT;}
    

    现在HEADERS 变量将通过读取使用mktemp 创建的临时文件填充到父shell 本身中。

    【讨论】:

    • 在分配给HEADERS 之后显示rm -f "$f" 会不会是个好主意?文件的中断、陷阱和清理呢?
    • 谢谢,我添加了trap 来清理临时文件。
    • 感谢这个版本,它也很好用。我接受了@JonathanLeffler 的解决方案,因为它避免了临时文件。
    猜你喜欢
    • 2018-08-10
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 2013-05-11
    • 1970-01-01
    • 2021-05-18
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多