замена процесса смешения и трубы в зш

Используя 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

Как видите, в этих 2-х из этих 3-х вариантов использования работают. Последнее меня здесь интригует. (Обратите внимание, что все команды работают с bash)

Можете ли вы объяснить, почему выходные данные функции, использующей подстановку процессов на входе, нельзя использовать через канал?

Я не ищу обходной путь, чтобы просто заставить мой пример работать. Я ищу объяснение, потому что я не мог его найти.

FYI sed здесь не имеет значения, я пробовал с несколькими другими командами (echo, cat...) и получил тот же результат.


person amine    schedule 06.05.2019    source источник
comment
Где именованная труба?   -  person Barmar    schedule 06.05.2019
comment
Вы говорите о замене процесса на <(...)?   -  person Barmar    schedule 06.05.2019
comment
да ‹(zcat myfile.gz)   -  person amine    schedule 06.05.2019
comment
вы можете смешивать подстановку процессов и каналы, так как это работает во второй команде. Я думаю, проблема в том, что вы пытаетесь использовать подстановку процесса в качестве аргумента функции.   -  person Barmar    schedule 06.05.2019
comment
Функция выполняется в подоболочке из-за канала, и эта подоболочка не наследует FD, подключенный к каналу.   -  person Barmar    schedule 06.05.2019


Ответы (1)


Когда вы передаете вывод функции ncat, он должен запускаться в подоболочке. По какой-то причине FD, подключенный к каналу замены процесса, не наследуется этой подоболочкой. Поскольку он использует /proc/self/fd, если FD не открыт в дочернем процессе, попытка чтения из него не удалась.

Мне это кажется ошибкой, поскольку в этом отношении функция должна работать аналогично внешним функциям.

Это не специфично для Linux, я воспроизвел проблему на MacOS с zsh 5.3.

Кажется, это происходит только тогда, когда подоболочка создается для канала. Чтобы увидеть, когда создается подпроцесс и наследуется ли FD, я изменил функцию на:

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

(/dev/fd — эквивалент /proc/self/fd для Mac.)

Если я побегу

(ncat <(gzcat myfile.gz )) 

Круглые скобки создают подоболочку, но FD, связанный с заменой процесса, отображается в выводе ls /dev/fd.

person Barmar    schedule 06.05.2019