프로세스의 표준 출력을 자체 표준 입력으로 리디렉션

프로세스의 표준 출력을 자체 표준 입력으로 리디렉션

나는 Haskell의 자기 참조 목록에 대해 생각하고 있습니다. 예를 들어 다음 스크립트가 있을 수 있습니다 fibonacci.hs.

#!/usr/bin/env runghc

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

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

파일 확장자가 매우 유사하기 때문에(약간 xp) 프로세스의 표준 출력을 자체 표준 입력에 추가하는 쉘 스크립트에 비슷한 것이 있어야 한다고 추론했습니다. 내가 생각할 수 있는 것은 다음과 같습니다 fibonacci.sh.

#!/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 스크립트가 표준 출력을 사용하면 이를 보존할 필요가 없습니다.

그렇다면 파일을 사용하여 이 작업을 수행하는 더 좋은 방법이 있습니까, 아니면 이상적으로는 파일 없이 리디렉션을 사용하여 이 작업을 수행하는 방법이 있습니까? 아니면 이것이 정말 나쁜 생각일까요? 명명된 파이프를 통해 이 작업을 수행할 수 있습니까?

무엇을 검색하려고 하든 나는 프로세스의 표준 출력을 다른 프로세스의 표준 입력에 추가하는 방법만 찾아냅니다. 이는 이미 어느 정도 익숙합니다. 양방향 파이프도 내가 원하는 것이 아닌 것 같습니다.

프로세스가 I/O를 너무 많이 버퍼링하지 않도록 주의가 필요하다는 것을 이해합니다.

답변1

~처럼Matthew Gunther는 그의 답변에서 지적했습니다.,ㅏ명명된 파이프("fifo")를 사용하면 스크립트가 자체 출력을 읽을 수 있습니다.

#!/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 3>mypipe

루프의 파이프에 쓰기 위해 추가 파일 설명자를 사용했는데, 이는 결과 시퀀스를 일반 출력 스트림(그리고이 목적으로 표준 오류 스트림을 오버로드하지 않습니다).

Python 코드를 이런 방식으로 사용하고 싶다면 다음을 수행할 수 있습니다.그것은 마치

#!/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 >mypipe

이 스크립트에서는 어떤 출력도 얻지 못한다는 것을 알 수 있습니다. 이는 Python 코드의 출력을 자체 입력으로 사용하기 때문입니다. 터미널에서 일부 출력을 얻으려면 위의 쉘 루프에서 비슷한 작업을 수행합니다(표준 출력이 아닌 다른 항목에 쓰기).

#!/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 >mypipe

여기서는 표준 오류 스트림을 (남용) 사용하여 터미널의 사용자에게 실제 결과를 제공합니다. 첫 번째 변형(새 파일 설명자를 통해 파이프의 출력 처리)과 같이 쉘 루프를 수행하면 더 깔끔하겠지만 Python에 대한 지식이 심각하게 부족합니다.

관련 정보