首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将进程的stdout重定向到它自己的stdin。

将进程的stdout重定向到它自己的stdin。
EN

Unix & Linux用户
提问于 2019-06-28 15:18:12
回答 1查看 979关注 0票数 3

我在考虑Haskell中的自引用列表--例如,您可能有以下脚本fibonacci.hs

代码语言:javascript
运行
复制
#!/usr/bin/env runghc

fibs :: [Integer]
fibs = 1:1:(zipWith (+) fibs $ tail fibs)

main :: IO ()
main = do
    mapM_ print $ take 50 fibs

由于文件名扩展名非常相似(只需要一个xp ),我推断在shell脚本中必须有类似的东西,将进程的stdout附加到它自己的stdin。我能想到的只有fibonacci.sh

代码语言:javascript
运行
复制
#!/usr/bin/env sh

{ echo 1; echo 1; } > fibonaccis

tail -f fibonaccis |
    python3 -c 'if True: # dummy to fix indentation
        b = int(input())
        for _ in range(48):
            a, b = b, int(input())
            print(a + b)' >> fibonaccis

cat fibonaccis

然而,我发现我不得不把所有的东西都写到一个文件中,这有点不令人满意。显然,这是一个玩具例子,有更多最优的已知算法,但是如果我只想生成第1000个斐波那契数呢?这样就没有必要保留Python脚本在使用它们之后编写的stdout行。

那么,是否有更好的方法来使用文件来完成这个任务,或者理想的情况下,只使用重定向就可以在没有文件的情况下做到这一点?或者这是一个非常糟糕的主意?也许用一个命名的管道就能做到这一点吗?

无论我试图搜索什么,都会想出一些方法将一个进程的标准附加到另一个进程的标准上,而我对此已经很熟悉了。双向管道似乎也不是我想要的。

我意识到,需要采取一些谨慎措施,以确保该过程不会过于宽松地缓冲其I/O。

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2019-06-30 08:39:39

作为马修斯·冈瑟在他的回答中指出,命名管道("fifo")可以用来获取脚本来读取自己的输出。

代码语言:javascript
运行
复制
#!/bin/bash

# Create pipe and arrange to remove it when done.
mkfifo mypipe
trap 'rm -f mypipe' EXIT

# Just to start off the sequence. Note that this
# needs to be a background process to avoid
# blocking, as there is nobody reading from the
# pipe yet.
echo '0 1' >mypipe &

# Numbers to produce. Note that the produced numbers
# will overflow at n=93.
n=48

# Read the two numbers from the pipe and put the
# last of these back together with the next number
# in the sequence:
while [ "$n" -gt 0 ] && read a b; do
        c=$(( a + b ))
        printf '%d %d\n' "$b" "$c" >&3

        # Also print the "b" number as output.
        printf '%d\n' "$b"

        n=$(( n - 1 ))
done mypipe

我使用了一个额外的文件描述符来写入循环中的管道,这样就可以正常地将生成的数字序列输出到标准输出流(并且不会重载此目的的标准错误流)。

如果您想在此方法中使用Python代码,则可能会执行以下操作

代码语言:javascript
运行
复制
#!/bin/bash

mkfifo mypipe
trap 'rm -f mypipe' EXIT

printf '%d\n%d\n' 0 1 >mypipe &

python3 -c 'if True: # dummy to fix indentation
    b = int(input())
    for _ in range(48):
        a, b = b, int(input())
        print(a + b)' mypipe

您会注意到,您没有从这个脚本中获得任何输出,这是因为我们使用Python代码的输出作为自己的输入。为了在终端中获得一些输出,我们应该在上面的shell循环中执行类似的操作(写入标准输出以外的内容):

代码语言:javascript
运行
复制
#!/bin/bash

mkfifo mypipe
trap 'rm -f mypipe' EXIT

printf '%d\n%d\n' 0 1 >mypipe &

python3 -c '
import sys
b = int(input())
for _ in range(48):
    a, b = b, int(input())
    print(a + b)
    print(b, file=sys.stderr)' mypipe

这里,我(ab-)使用标准错误流向终端中的用户提供实际结果。如果像第一个变体中的shell循环那样(通过一个新的文件描述符处理管道的输出),它会更整洁,但是我对Python的知识严重缺乏。

票数 3
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/527501

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档