Множественный стандартный ввод? Как?

36

Из этого поста командной строки :

$ diff <(wget -q -O - URL1) <(wget -q -O - URL2)

Похоже на несколько стандартных вводов, но - если я правильно помню свой курс по программированию Linux - это не может быть. Я думал, что по определению стандартный ввод был одним потоком.

Возможно это имеет отношение к stdin? Может кто-то объяснить это мне; возможно, предоставьте ссылки на документацию.

Бонус: как скрипт будет обрабатывать эти несколько потоков? Если бы кто-то мог привести пример Python или Perl, это было бы очень полезно.

Бельмин Фернандес
источник
1
Хороший вопрос. Если вы не знаете, есть сайт вопросов и ответов для Unix / Linux: unix.stackexchange.com
Мэтт Эллен,
2
Документация для замены процесса: gnu.org/software/bash/manual/bashref.html#Process-Substitution
Гленн Джекман,
Примечание: в Bash это <(…); В Zsh синтаксис подстановки процесса есть =(…).
Камиль Мачоровский

Ответы:

27

Это не множественный стандартный ввод. Это bash'ism, который называется «Замена процесса» http://tldp.org/LDP/abs/html/process-sub.html

Создает псевдофайл ( /dev/fd/something) для каждой замены. Это довольно полезно. Команду можно читать только как поток, то есть она не может идти вперед и назад с помощью fseek. Нужно читать это как поток байтов, как канал.

БОНУС Ответ

Вам не нужно делать слишком много, чтобы использовать это. Что касается вашего сценария, он получает действительное имя файла в командной строке, которое может быть открыто () как любой другой. Как уже говорили другие, вы увидите diff /dev/fd/XX /dev/fd/YY. Если вы выполните stat () для любого из этих псевдофайлов, вы увидите, что это именованный канал, и вам следует использовать семантику канала, а именно: fseek () или ftell (). Если вы делаете тест стат () явно увидеть , если это файл (например [ -f $1 ]) , это будет перерыв - это реализуется в виде именованного канала в конце концов.

Рич Гомолка
источник
Еще один хороший справочник по подмене процессов bash - wiki.bash-hackers.org/syntax/expansion/proc_subst
studgeek
И какое рекомендуемое использование этой функции? Поддерживаете ли вы, когда ваша программа может разумно работать с потоком вместо того, чтобы требовать файл с произвольным доступом?
masterxilo
7

<(...)делает процесс подстановки в bash. Выходные данные процесса в скобках отправляются в дополнительный дескриптор файла, выходящий за пределы нормального значения 3, и возвращается имя файла, соответствующее этому дескриптору файла. Таким образом, вывод команды может быть обработан как имя файла для передачи другой команде.

Игнасио Васкес-Абрамс
источник
7

Существует один stdinи один stdout для каждого процесса . Обычно они подключены к терминалу, но их можно перенаправить отдельно друг от друга.

В этом примере wgetзадействованы два процесса, каждый из которых получает свой собственный stdinи stdout. Каждый wgetпроцесс пишет -, что его stdout. Затем bashподстановка процесса <(...)соединяет stdoutпроцесс с уникальным псевдофайлом, из которого diffможно читать. Обратите внимание, что две замены процесса дают два разных псевдофайла! Таким образом, diffвидит что-то вроде:

diff /dev/fd/XX /dev/fd/YY

где stdoutиз wget -q -O - URL1подключен /dev/fd/XX, и stdoutиз wget -q -O - URL2к /dev/fd/YY.

musiphil
источник