0

使用 ZSH,我试图将 sed 命令包装到一个函数中,然后使用它,同时将管道与进程替代混合。让我用一个例子来解释:

$ echo "test text" | gzip > myfile.gz
$ sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g' <(zcat myfile.gz) | more
test text
$ ncat() { sed $'s,\x1b\\[[0-9;]*[a-zA-Z],,g' $@; }
$ zcat myfile.gz | ncat | more
test text
$ ncat <(zcat myfile.gz) | more
sed: can't read /proc/self/fd/13: No such file or directory

如您所见,在这 3 种用法中的 2 种中有效。最后一个是这里让我感兴趣的一个。(请注意,所有命令都适用于 bash)

你能解释为什么在输入中使用进程替换的函数的输出不能通过管道使用吗?

我不是在寻找一种解决方法来使我的示例正常工作。我正在寻找解释,因为我找不到。

仅供参考sed,这里不相关,我尝试了多个其他命令(echo,cat ...),并得到了相同的结果

4

1 回答 1

0

当您通过管道ncat传输函数的输出时,它必须在子 shell 中运行。由于某种原因,连接到进程替换管道的 FD 没有被此子 shell 继承。由于它使用/proc/self/fd,如果 FD 未在子进程中打开,则尝试读取它会失败。

这对我来说似乎是一个错误,因为在这方面一个函数应该与外部函数类似地工作。

这不是 Linux 特定的,我在运行 zsh 5.3 的 MacOS 上重现了该问题。

它似乎只在为管道创建子外壳时发生。要查看何时创建子进程以及是否继承了 FD,我将函数更改为:

ncat() { echo $$;sh -c 'echo $PPID';echo "$@";ls /dev/fd; }

/dev/fd是 Mac 的等价物/proc/self/fd。)

如果我跑

(ncat <(gzcat myfile.gz )) 

括号创建一个子shell,但与进程替换关联的FD显示ls /dev/fd输出中。

于 2019-05-06T15:22:00.830 回答