bash - 如何在 bash 中制作管道循环

标签 bash

假设我有程序 P0 , P1 , ... P(n-1)对于一些 n > 0 .如何轻松重定向程序 Pi 的输出编程 P(i+1 mod n)对于所有 i ( 0 <= i < n )?

例如,假设我有一个程序 square ,它重复读取一个数字然后打印该数字的平方,还有一个程序 calc ,它有时会打印一个数字,之后它希望能够读取它的平方。我如何连接这些程序,以便无论何时 calc打印一个数字,square平方它返回到calc

编辑:我应该澄清一下“轻松”的意思。命名管道/fifo 解决方案确实有效(我过去曾使用过),但如果将其与使用 bash 管道进行比较,它实际上需要相当多的工作才能正确完成。 (你需要得到一个还不存在的文件名,用那个名字创建一个管道,运行“管道循环”,清理命名管道。)想象一下你不能再写 prog1 | prog2并且总是必须使用命名管道来连接程序。

我正在寻找几乎与编写“普通”管道一样简单的东西。例如类似 { prog1 | prog2 } >&0 的东西会很棒。

最佳答案

在昨天花了很长时间尝试将 stdout 重定向到 stdin 之后,我最终得到了以下方法。它不是很好,但我认为我更喜欢它而不是命名管道/fifo 解决方案。

read | { P0 | ... | P(n-1); } >/dev/fd/0

{ ... } >/dev/fd/0 是将整个管道序列的 stdout 重定向到 stdin(即将 P(n-1) 的输出重定向到P0的输入)。使用 >&0 或类似的东西不起作用;这可能是因为 bash 假定 0 是只读的,而它不介意写入 /dev/fd/0

初始的 read 管道是必需的,因为没有它,输入和输出文件描述符都是相同的 pts 设备(至少在我的系统上是这样),并且重定向无效。 (pts 设备不能用作管道;向它写入内容会将内容显示在屏幕上。)通过使 { ... } 的输入成为普通管道,重定向具有预期的效果.

用我的calc/square 例子来说明:

function calc() {
  # calculate sum of squares of numbers 0,..,10

  sum=0
  for ((i=0; i<10; i++)); do
    echo $i                   # "request" the square of i

    read ii                   # read the square of i
    echo "got $ii" >&2          # debug message

    let sum=$sum+$ii
  done

  echo "sum $sum" >&2           # output result to stderr
}

function square() {
  # square numbers

  read j                         # receive first "request"
  while [ "$j" != "" ]; do
    let jj=$j*$j
    echo "square($j) = $jj" >&2  # debug message

    echo $jj                     # send square

    read j                       # receive next "request"
  done
}

read | { calc | square; } >/dev/fd/0

运行上面的代码会得到以下输出:

square(0) = 0
got 0
square(1) = 1
got 1
square(2) = 4
got 4
square(3) = 9
got 9
square(4) = 16
got 16
square(5) = 25
got 25
square(6) = 36
got 36
square(7) = 49
got 49
square(8) = 64
got 64
square(9) = 81
got 81
sum 285

当然,这种方法有点hack。特别是 read 部分有一个不受欢迎的副作用:“真实”管道循环的终止不会导致整体的终止。我想不出比 read 更好的方法了,因为似乎您只能通过尝试向其写入内容来确定管道循环已终止。

关于bash - 如何在 bash 中制作管道循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40244/

相关文章:

linux - bash 启动时更改目录

bash - AWK 不会在输出区域设置中过滤十进制形式的数字 100 (100.000)

windows - 从Git Bash(MINGW64)运行MSVC 'cl.exe'

php - 从 php 执行的 Shell 脚本,但 sh 脚本中的命令不会运行

regex - 计算正则表达式的唯一出现次数

php - 为什么结果等于 0,有时等于 1 - shell_exec('pgrep -f

linux - gz 文件的递归 grep 从输出字符串中搜索字符串

python - 尝试运行 Python 脚本时出现令人困惑的错误

linux - 重新激活 python 脚本 - Linux bash 脚本

linux - 如何构建延迟/缓冲管道?