Передача двух аргументов в команду с использованием каналов

22

Обычно нам нужно передать только один аргумент:

echo abc | cat
echo abc | cat some_file -
echo abc | cat - some_file

Есть ли способ передать два аргумента? Что-то вроде

{echo abc , echo xyz} | cat
cat `echo abc` `echo xyz`

Я мог бы сначала сохранить оба результата в файле

echo abc > file1
echo xyz > file2
cat file1 file2

Но тогда я мог бы случайно перезаписать файл, что не очень хорошо. Это входит в неинтерактивный скрипт. По сути, мне нужен способ передать результаты двух произвольных команд catбез записи в файл.


ОБНОВЛЕНИЕ: Извините, пример маскирует проблему. Хотя { echo abc ; echo xyz ; } | catкажется, что работает, выход из-за echos, а не cat.

Лучшим примером будет то, { cut -f2 -d, file1; cut -f1 -d, file2; } | paste -d,что не работает, как ожидалось.

С

file1:
a,b
c,d

file2:
1,2
3,4

Ожидаемый результат:

b,1
d,3

ПОСТАНОВИЛИ:

Используйте процесс подстановки :cat <(command1) <(command2)

Или создайте именованные каналы, используя mkfifo:

mkfifo temp1
mkfifo temp2
command1 > temp1 &
command2 > temp2 &
cat temp1 temp2

Менее элегантный и более многословный, но отлично работает, если вы убедитесь, что temp1 и temp2 не существуют до этого.

goweon
источник
1
Это заставляет меня почесать голову. Вы хотите передать две разные команды одному коту?
user606723
2
Вы знаете, что «трубопровод» и «аргументы» - это две совершенно не связанные концепции, верно?
Игнасио Васкес-Абрамс
@ Игнасио, эээ ... Я не так хорошо знаком с Linux, поэтому не очень понимаю разницу. Я всегда думал, что пайпинг означает, что он принимает предыдущий результат в качестве аргумента. Хотите просветить меня?
Goweon
@firebat no, pipe означает принимать стандартный вывод предыдущей команды как стандартный ввод следующей команды. Вы все еще можете иметь аргументы, которые представляют собой другое понятие.
Богатая Гомолка
Кроме того, что касается вашего текста обновления, выходные данные поступают от cat, просто вы хотите, чтобы операторы казались отделенными от cat, чего он не может сделать, поскольку они сериализуются в один поток.
Богатая Гомолка

Ответы:

17

Я думаю, что вы хотите «Заменить процесс» http://tldp.org/LDP/abs/html/process-sub.html . Он также работает на zsh, хотя у него больше опций и синтаксис может отличаться.

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

Ваши примеры работают как подстановка процесса:

cat <(echo abc) <(echo xyz)
paste -d, <(cut -f2 -d, file1) <(cut -f1 -d, file2)

Думайте об этом как об инструменте для использования процесса, и пусть он притворяется файлом без каких-либо временных файлов.

(из моего предыдущего ответа )

Рич Гомолка
источник
2

Фактически, фигурные скобки сработали, потому что оператор канала подключит стандартные выходы сгруппированных команд к стандартному входу третьего.

Вы можете сказать, что распечатка не из эха, выполнив любую команду, которая не использует стандартный ввод, например { echo 1; echo 2;} | echo 3напечатает 3 вместо 1 \ n2 \ n3.

Однако это не то, что вы хотели, потому что две команды в фигурных скобках записывают в один и тот же вывод, что похоже на catих результаты. Чтобы сгенерировать два разных результата для использования в качестве двух аргументов для таких команд, как paste, вам нужно будет использовать временный файл или именованный канал.

Вы можете использовать mktempдля создания уникального временного файла или mkfifoдля создания файла канала FIFO.

billc.cn
источник
Большое спасибо за ваш ответ, я искал много дней для этого решения и, наконец, нашел ваш ответ здесь.
Саид Фальсафин
2

Мне нравится xargs. В качестве примера я хочу найти размер всех каталогов данных mysql в / usr / local

osx: локальный пользователь $ pwd
/ USR / местные
osx: локальный пользователь $ ls | grep mysql
MySQL
MySQL-5.0.51a-osx10.5-x86_64
MySQL-5.0.51b-osx10.5-x86_64
MySQL-5.1.39-osx10.5-x86_64
MySQL-5.6.17-osx10.7-x86_64
os x: локальный пользователь $ ls | grep mysql | sudo xargs du -sh
4.0K mysql
2.8G mysql-5.0.51a-osx10.5-x86_64
 10G mysql-5.0.51b-osx10.5-x86_64
 25G mysql-5.1.39-osx10.5-x86_64
753M mysql-5.6.17-osx10.7-x86_64
osx: локальный пользователь $ 

xargs

мазок
источник