【问题标题】:In a bash function, how do I get stdin into a variable在 bash 函数中,如何将 stdin 放入变量中
【发布时间】:2015-09-02 22:02:18
【问题描述】:

我想用管道调用一个函数,并将所有标准输入读入一个变量。

我读到正确的方法是使用read,或者read -rread -a。但是,我在实践中遇到了很多问题(尤其是多行字符串)。

最后还是选择了

function example () {
  local input=$(cat)
  ...
}

这样做的惯用方法是什么?

【问题讨论】:

  • 您需要将所有输入都放在一个字符串中还是需要对管道数据进行分段操作?
  • 您是否尝试过类似read -r -d\0 input 的方法(假设您的输入不包含任何空字符)?这将为每个函数调用节省一个进程。不过我相信$(cat) 解决方案更具可读性。
  • 我认为这样做的惯用方法是不这样做。相反,在您打算使用该变量的地方读取 stdin 而不是使用该变量。如果您需要多次引用数据,请找出一种重构工作的方法,这样就没有必要了。你打算如何使用这个变量?
  • @williamPursell 我想先保存这一切,因为我想在处理它之前做其他事情(例如调用其他函数,声明其他变量等)。
  • 除非您计划做的其他事情会消耗​​标准输入,否则您可以先执行它们而无需担心stdin,直到您需要它。并且将其存储在一个变量中将需要存储内存并在您的其他工作甚至可以开始之前将其全部使用。

标签: linux bash shell


【解决方案1】:

input=$(cat) 是一个非常好的方法来捕获标准输入,如果你真的需要的话。需要注意的是,命令替换会删除所有尾随换行符,因此,如果您想确保也捕获这些换行符,则需要确保最后读取除换行符之外的其他内容。

input=$(cat; echo x)
input=${input%x}   # Strip the trailing x

bash 4 或更高版本中的另一个选项是使用readarray 命令,该命令将使用标准输入的每一行填充一个数组,每个元素一行,然后如果需要,您可以将其加入单个变量.

readarray foo
printf -v foo "%s" "${foo[@]}"

【讨论】:

    【解决方案2】:

    我发现使用 cat 与基于我运行的测试的其他方法相比确实很慢:

    local input="$(< /dev/stdin)"
    

    如果有人想知道,&lt; 只是输入重定向。来自 bash 黑客wiki

    当内部命令只是一个输入重定向,没有别的, 例如

    $( <FILE )
    # or ` <FILE `
    

    然后 Bash 尝试读取给定的文件并在给定的情况下采取行动 命令是cat FILE


    关于便携性的说明

    就这种方法的可移植性而言,您可能会在整个 linux 桌面生命周期中使用,并且永远不要使用没有 /dev/stdin 的 linux 系统,但如果您想满足这种要求,这里是question on Unix Stackexchange 质疑直接访问 /dev/{stdin,stdout,stderr} 和朋友的可移植性。

    我在使用 linux 容器(例如使用 docker 或 buildah 构建的容器)时遇到的另一件事是,在某些情况下,/dev/stdin 甚至 /dev/stdout 在内部不可用容器。我无法最终说出是什么原因造成的。

    【讨论】:

    • 太棒了!想解释一下$() 内部的&lt; 是如何工作的?
    • @TeddyC 我只是用解释更新答案
    【解决方案3】:

    在 SO 上存在一些重叠/非常相似的问题。我在这里回答了这个问题,使用了 read 内置:

    https://stackoverflow.com/a/58452863/3220983

    然而,在我的回答中,我只关心行。

    cat 方法的可争论的弱点是它需要生成一个子shell。否则,它是一个很好的方法。这可能是处理多行处理的最简单方法,具体查询here。

    认为read 方法在尝试链接大量命令或重复调用函数的列表时更快/更节省资源。

    【讨论】:

      猜你喜欢
      • 2016-03-29
      • 2011-12-19
      • 2012-04-14
      • 2011-05-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-08
      相关资源
      最近更新 更多