您如何在没有它的 shell 中实现进程替换(使用 bash 脚本)?

dgo*_*o.a 5 process-substitution mksh

我已经看到 Fish shell 将进程替换作为一个函数来实现:

# === Fish shell lang:
function psub
   mkfifo $the_pipe
   cat >$the_pipe &
   echo $the_pipe
   # remove pipe when bg job is done
end  

# Example:
diff (echo abc | psub)  (echo def | psub)
Run Code Online (Sandbox Code Playgroud)

完整代码:https : //github.com/fish-shell/fish-shell/blob/master/share/functions/psub.fish

我已经尝试了几个小时为非鱼壳 (mksh) 重新实现它,但无法做到:

# Executable file:  my.psub.sh
the_pipe="$(mktemp /tmp/pipe.XXXXXXXXXX)"
mkfifo $the_pipe
cat >$the_pipe &
echo $the_pipe

# Example:
diff $(echo abc | my.psub.sh)  $(echo def | my.psub.sh)
Run Code Online (Sandbox Code Playgroud)

命令方块。我已经尝试了我能想到的所有方法,但我不知道下一步该去哪里。

mir*_*los 3

它\xe2\x80\x99s有点困难但可行:

\n\n
function die {\n        print -ru2 -- "E: $*"\n        exit 1\n}\n\nfunction psubin {\n        local stdin=$(cat; echo .) pipe\n\n        pipe=$(mktemp /tmp/psub.XXXXXXXXXX) || die mktemp\n\n        # this is racy\n        rm -f "$pipe"\n        mkfifo "$pipe" || die mkfifo\n\n        (\n                # don\xe2\x80\x99t block parent\n                exec <&- >&- 2>&-\n                # write content to FIFO\n                print -nr -- "${stdin%.}" >"$pipe"\n                # signal EOF to reader, ensure it\xe2\x80\x99s not merged\n                sleep 0.1\n                :>"$pipe"\n                # clean up\n                (sleep 1; rm -f "$pipe") &\n        ) &\n        print -nr -- "$pipe"\n}\n\ndiff -u $(echo abc | psubin) $(echo def | psubin)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我和你在这里遇到的问题是:

\n\n
    \n
  • mkfifo除非你rm mktemp先 \xe2\x80\x99s 输出,否则会抱怨
  • \n
  • 如果 mksh 仍然与父进程共享任何文件描述符(stdin、stdout、stderr),则 mksh 会阻止后台进程(注意:这可能是使用而>&-不是 的唯一有效用例>/dev/null,并且只是因为我们可以保证这些 fd 不再被使用,也不被任何新的 fd 取代)
  • \n
  • 因为我们在后台进程中没有\xe2\x80\x99t的标准输入,所以\xe2\x80\x99需要缓存其内容,字节精确
  • \n
  • 带有 FIFO(命名管道)的 EOF 并非易事。让\xe2\x80\x99s 留在那个\xe2\x80\xa6 上(我们可以尝试一些技巧,尝试以非阻塞方式打开 FIFO,以检查是否有\xe2\x80\x99s 读取器,并发出 EOF 信号,直到读者死了,但目前效果很好)
  • \n
  • 如果使用后删除 FIFO,则\xe2\x80\x99 会更好\xe2\x80\xa6
  • \n
\n\n

另一方面:好事我们\xe2\x80\x99现在正在这样做,因为我最终希望实现<(\xe2\x80\xa6)到mksh本身,然后我需要知道要注意什么,因为我们可以\xe2\x80\x99t像 GNU bash 一样使用/dev/fd/,因为 \xe2\x80\x99s 不够可移植。

\n