답변1
이 기능은 ksh
도입되었으며(ksh86에 처음 문서화됨) 사용 중입니다(이전에 일부 BSD 및 AT&T 시스템에 독립적으로 추가됨). ksh93u 및 이전 버전에서는 시스템이 지원하지 않는 한 zsh, bash 이상에서는 사용할 수 없는 경우 임시 명명된 파이프(System III에 추가된 명명된 파이프)를 사용할 수 있습니다./dev/fd/n
ksh
/dev/fd/n
ksh93u+
/dev/fd/n
사용 가능한 시스템(POSIX에서 지정하지 않음)에서는 프로세스 대체를 직접 수행할 수 있습니다(예: )./dev/fd/n
diff <(cmd1) <(cmd2)
{
cmd1 4<&- | {
# in here fd 3 points to the reading end of the pipe
# from cmd1, while fd 0 has been restored from the original
# stdin (saved on fd 4, now closed as no longer needed)
cmd2 3<&- | diff /dev/fd/3 -
} 3<&0 <&4 4<&- # restore the original stdin for cmd2
} 4<&0 # save a copy of stdin for cmd2
ksh93
그러나 쉘 파이프는 파이프가 아닌 소켓 쌍으로 구현되고 /dev/fd/3
소켓 위치를 가리키는 fd 3을 여는 것이 Linux에서 작동하지 않기 때문에 Linux에서는 작동하지 않습니다 .
POSIX는 이를 지정하지 않지만 명명된 파이프를 지정합니다. 명명된 파이프는 파일 시스템에서 액세스할 수 있다는 점을 제외하면 일반 파이프처럼 작동합니다. 여기서 문제는 임시 파일을 생성하고 나중에 정리해야 한다는 것입니다. 특히 POSIX에는 임시 파일이나 디렉터리 생성 및 신호 처리를 위한 표준 메커니즘(일부 시스템의 메커니즘과 같은)이 없다는 점을 고려하면 이는 안정적으로 수행하기 어렵습니다. (중단 또는 종료 시 정리) 포팅도 어렵습니다./dev/fd/n
mktemp -d
다음을 수행할 수 있습니다.
tmpfifo() (
n=0
until
fifo=$1.$$.$n
mkfifo -m 600 -- "$fifo" 2> /dev/null
do
n=$((n + 1))
# give up after 20 attempts as it could be a permanent condition
# that prevents us from creating fifos. You'd need to raise that
# limit if you intend to create (and use at the same time)
# more than 20 fifos in your script
[ "$n" -lt 20 ] || exit 1
done
printf '%s\n' "$fifo"
)
cleanup() { rm -f -- "$fifo"; }
fifo=$(tmpfifo /tmp/fifo) || exit
cmd2 > "$fifo" & cmd1 | diff - "$fifo"
cleanup
(여기서는 신호 처리를 고려하지 않습니다.)
답변2
이를 달성하려면 heredoc 및 /dev/fd/n 파일을 사용할 수 있습니다. 예를 들어 bash
다음과 같이 할 수 있습니다.
#!/usr/bin/env bash
paste <(echo "$SHELL") <(echo "$TERM") <(echo "$LANG")
하지만 POSIX sh에서는 다음을 수행해야 합니다.
#!/bin/sh
paste /dev/fd/3 3<<-EOF /dev/fd/4 4<<-EOF /dev/fd/5 5<<-EOF
$SHELL
EOF
$TERM
EOF
$LANG
EOF
출력은 동일합니다.
질문에 대답하려면 다음과 같이 작동합니다.
#!/bin/sh
diff /dev/fd/3 3<<-EOF /dev/fd/4 4<<-EOF
$(sort file1)
EOF
$(sort file2)
EOF
투박해 보이지만 작동합니다.
답변3
유용한 변수를 잃지 않으려면 cmd | while read A B C
다음을 수행하세요.
VAR="before"
while read A B C
do
VAR="$A $VAR"
done < <(cmd)
echo "$VAR"
당신은 그것을 사용할 수 있습니다 :
VAR="before"
while read A B C
do
VAR="$A $VAR"
done << EndOfText
`cmd`
EndOfText
echo "$VAR"
따라서 이 질문에 답하려면 다음과 같이 하십시오.
sort file1 | diff /dev/stdin /dev/stdout 2<<EOT
`sort file2`
EOT