【问题标题】:mixing process substitution and pipes in zsh在 zsh 中混合进程替换和管道
【发布时间】:2019-05-06 15:02:34
【问题描述】:

使用 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...),得到了相同的结果

【问题讨论】:

  • 命名管道在哪里?
  • 您是在用&lt;(...) 谈论进程替换吗?
  • 您可以混合使用进程替换和管道,因为它适用于第二个命令。我认为问题在于您试图将进程替换用作函数的参数。
  • 该函数由于管道而在子shell中运行,并且该子shell不继承连接到管道的FD。

标签: linux pipe zsh process-substitution


【解决方案1】:

当您通过管道传递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 输出中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 1970-01-01
    • 1970-01-01
    • 2015-03-19
    相关资源
    最近更新 更多