20

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

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 , кажется, работает, результат - echo , а не 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 не существуют до этого.

3 ответа3

16

Я думаю, что вы хотите «Заменить процесс» 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

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

osx:local user$ pwd
/usr/local
osx:local user$  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:local user$  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:local user$ 

xargs

1

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .