当前位置:  开发笔记 > 编程语言 > 正文

如何在bash中创建一个管道循环

如何解决《如何在bash中创建一个管道循环》经验,为你挑选了3个好方法。

假设我有计划P0,P1... P(n-1)一些n > 0.如何轻松地将程序输出重定向PiP(i+1 mod n)all i(0 <= i < n)的程序?

例如,假设我有一个程序square,它重复读取一个数字而不是打印该数字的正方形,以及一个程序calc,它有时打印一个数字,之后它希望能够读取它的平方.如何连接这些程序,以便每当calc打印一个数字时,square它会将它返回到calc

编辑:我应该用"轻松"来澄清我的意思.命名管道/ fifo解决方案确实有效(我过去曾使用过),但如果将它与使用bash管道进行比较,它实际上需要相当多的工作才能正常工作.(您需要获取一个尚未存在的文件名,使用该名称创建一个管道,运行"管道循环",清理命名管道.)想象一下,您无法再写prog1 | prog2,并且总是必须使用命名管道来连接程序.

我正在寻找像写"普通"管道一样简单的东西.比如说{ prog1 | prog2 } >&0会很棒.



1> mweerden..:

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

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

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

初始read-pipe是必要的,因为如果没有它,输入和输出文件描述符都是相同的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

当然,这种方法相当有点黑客.特别是该read部件具有不希望的副作用:"实际"管道回路的终止不会导致整体的终止.我想不出更好的事情,read因为你似乎只能通过尝试写一些东西来确定管道循环已经终止.



2> Douglas Leed..:

命名管道可能会这样做:

$ mkfifo outside
$ outside &
$ echo "1" >outside ## Trigger the loop to start



3> Mark Witczak..:

这是一个非常有趣的问题.我(含糊地)记得17年前大学里的任务非常相似.我们必须创建一个管道数组,我们的代码将获取每个管道的输入/输出的文件句柄.然后代码将分叉并关闭未使用的文件句柄.

我想你可以用bash中的命名管道做类似的事情.使用mknod或mkfifo创建一组具有您可以引用的唯一名称的管道,然后分叉您的程序.

推荐阅读
夏晶阳--艺术
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有