【问题标题】:In Bash, how do I stream the end of a pipeline into a variable?在 Bash 中,如何将管道的末端流式传输到变量中?
【发布时间】:2015-07-12 13:24:42
【问题描述】:

我知道在管道末尾设置的任何变量都会丢失(不包括 Bash 4 中的 shell 选项 - 不幸的是,这需要是一个可移植的解决方案)。但是,我确信必须有一种方法使用文件描述符或其他东西将管道末端的输出流式传输到变量中,即使通过一些复杂的路由! :)

理想情况下,我想要一个带有一个参数的命令/函数,一个变量的名称,最终将导致包含管道其余部分的输出。

我有一个函数可以以可移植的方式找到它的下一个空闲文件描述符:

getFd ()
{
    # we'll start with 3 since 0..2 are mapped to standard in, out, and error respectively
    local myFD='3'
    # we'll get the upperbound from bash's ulimit
    local FD_MAX=$( ulimit -n )
    local FD_LOC
    if [ -e /proc/$$/fd ]
    then
        FD_LOC="/proc/$$/fd"
    elif [ -e /dev/fd ]
    then
        FD_LOC="/dev/fd"
    else
        return 1
    fi
    while [ -e "${FD_LOC}/${myFD}" ] && [ "${myFD}" -le "${FD_MAX}" ]
    do
        ((++myFD))
    done
    eval FD="${myFD}"
}

我想我可能需要做一些事情,比如以前创建一个打开的文件描述符池,可以通过一些别名 jiggery pokey 或其他东西拉入,但我希望我错过了一些更简单的方法,因为我确信必须有做一个更好的方法。

我还在想,如果我在末尾添加printf %s "${myFD}",我可以执行alias '{FD}'="$( getFd )" 之类的操作来实现自动查找下一个可用文件描述符以{FD} <filename 形式使用的Bash 4 功能注意:需要有一个空间,但是如果可以使它起作用,那么将这个特性带到 bash 3.0 中会很棒。另外,可能必须使用shopt -s expand_aliases

任何想法将不胜感激!

附:我试图避免强制使用 MyCommand MyVariable < <( command1 | command2 ; ) ; 类型语法,并且我正在努力是否可以以:$ command1 | command2 | MyCommand MyVariable ; 使用类型结束。

【问题讨论】:

  • 您似乎正在尝试做一些对于 shell 脚本来说太复杂的事情。考虑改为编写 Perl 或 Python 脚本。
  • 你的问题听起来很有趣,但并不容易理解。以下是您的读者可能会问自己的一些问题:为什么这些变量会丢失?你在说什么外壳选项?管道的哪一端——我以为他们有两个?他们为什么不直接使用命令替换?这能解决什么问题还是只是语法糖?
  • 该功能是如何工作的? FD_LOC 中的 $$ 没有在我能看到的任何地方展开。还有为什么eval 在最后一行?
  • 我假设您想要的不仅仅是让函数将内容写入预先安排的(或通过数字传递的)fd,然后在下一行读取?您想为此获得所需的运行环境有多“棘手”?我认为您无法让命令本身执行此操作,因此您需要环境中的 something 在某处进行变量设置。
  • 嘿,$$ 是一个标准的“特殊”bash 变量(我相信也是 Bourne),它为您提供了评估时所处的 shell 的 PID。这与那些使用/proc 文件系统来确定下一个可用fd 的结构有关,因为结构是/proc/<pid>/fd/<fd>,其中<pid> 是shell 的pid,而 是驻留在那里的文件描述符文件。这是一种语法糖,尽管我正在使用它来构建一种更友好和更明智的方式,通过一些非常需要的语言扩展来处理 shell。 :)

标签: linux bash shell unix scripting


【解决方案1】:

您的问题有点令人困惑,但我猜您想将用户定义的变量名称设置为第一个可用的文件描述符。

如果是这种情况,您的函数应该简单地回显 fd 编号:

getFD() {
  ...
  echo $myFD
}

然后假设foo包含存储fd的变量名,假设它包含字符串bar

eval $foo=`getFD`

在变量 bar 之后将包含第一个可用的 fd。

【讨论】:

  • 嘿,谢谢你,虽然不幸的是我要做的比这复杂得多。我已经将 FD 变量设置为下一个可用的文件描述符的函数。正如我在我的问题中所说,我已经尝试在最后添加一个 echo (只是以 printf 的形式来保持它的干净和便携,最后没有 [CR]),但是,我想要的是一个函数或命令可以以某种方式执行,可能带有一些别名转换,以将导致该命令执行的管道流式传输到其第一个 arg 中给出的 var 名称中。
  • 例如:$ someCommand | anotherCommand | myCommand nameOfVarToSet 其中nameOfVarToSet 是一个导出的变量,其中包含如果myCommand 不存在,将在终端上显示的所有文本。另一个词 nameOfVarToSet 包含用户在运行时会看到的内容:$ someCommand | anotherCommand # 本身,问题在于管道中的每个命令都是一个子shell(不包括 bash4:$ set +m ; shopt -s lastpipe 方法)
猜你喜欢
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多