Есть ли способ предоставить stdin / out вместо файла для программы в Unix? - PullRequest
6 голосов
/ 04 ноября 2010

У меня есть утилита командной строки от стороннего производителя (она большая и написана на Java), которую я использую для обработки некоторых данных.Эта утилита ожидает информацию в файле с разделителями строк, а затем выводит обработанные данные в STDOUT.

На моих этапах тестирования я справился с написанием некоторого Perl для создания файла, полного информации для обработки, и последующей отправкой этого файла.в эту стороннюю утилиту, но поскольку я близок к запуску этого кода в производство, я действительно предпочел бы просто направить данные в эту утилиту напрямую, а не сначала записывать эти данные в файл, так как это избавило бы меня от необходимостизаписать ненужную информацию на диск.Есть ли способ сделать это в Unix?

В настоящее время я вызываю утилиту следующим образом:

bin/someapp do-action --option1 some_value --input some_file

Я хотел бы сделать что-то вроде:

bin/someapp do-action --option1 some_value --input $piped_in_data

Возможно ли что-либо подобное без моей модификации стороннего приложения?

Ответы [ 4 ]

10 голосов
/ 04 ноября 2010

Вы должны использовать / dev / stdin:

bin/someapp do-action --option1 some_value --input /dev/stdin

(Обратите внимание, что в некоторых системах / dev / stdin является символической ссылкой; если ваша Java-программа не справляется с этим, вам, возможно, придется использовать / dev / fd / 0 или что-то подобное.)

10 голосов
/ 04 ноября 2010

Вы можете использовать «процесс подстановки» в bash для достижения чего-то похожего на то, что вы хотите.

bin/someapp do-action --option1 some_value --input <(generate_input.sh)

должен сделать свое дело. <(list) часть - это подстановка процесса.

2 голосов
/ 02 февраля 2015

Это не так просто./ dev / stdin, именованные каналы и подстановка процесса <() не доступны программе так же, как файл.В частности, невозможно использовать fseek (), fsetpos () внутри такой конструкции, потому что ее длина априори неизвестна.работать хоть.Так что для большинства программ, которые просто читают входные данные построчно или символ за символом, это подойдет. </p>

Если ваша программа ищет в файле (и, возможно, выполняет другие «более сложные» операции), вам нужно создать временныйфайл к сожалению.

2 голосов
/ 06 ноября 2010

Другой способ, если метод /dev/stdin по какой-то причине не подходит, - это использование «именованного канала».

Если вы делаете

% mkfifo /path/to/file

тогда это создаст объект файловой системы с таким именем, который может действовать как канал между двумя процессами. Это то же самое, что и с обычным каналом, за исключением того, что процессы могут ссылаться на канал, как если бы это был обычный файл. Например:

% mkfifo /tmp/my-fifo
% grep alias ~/.bashrc >/tmp/my-fifo &
[1] 70134
% sed 's/alias/wibble/' /tmp/my-fifo
wibble ls='ls -F'
....
[1]  + done       grep alias ~/.bashrc > /tmp/my-fifo
% 

Здесь команда grep записывает в FIFO точно так же, как если бы это был обычный файл, и блокируется, когда буфер именованного канала заполняется. Процесс sed читает из канала (как если бы это был обычный файл), освобождая при этом буфер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...