Passando dois argumentos para um comando usando pipes

22

Normalmente, precisamos apenas passar um argumento:

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

Existe uma maneira de passar dois argumentos? Algo como

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

Eu poderia apenas armazenar os dois resultados em um arquivo primeiro

echo abc > file1
echo xyz > file2
cat file1 file2

Mas então, sobrescrevi acidentalmente um arquivo, o que não está ok. Isso está entrando em um script não interativo. Basicamente, preciso de uma maneira de passar os resultados de dois comandos arbitrários catsem gravar em um arquivo.


UPDATE: Desculpe, o exemplo mascara o problema. Embora { echo abc ; echo xyz ; } | catpareça funcionar, a saída é devida ao echos, não ao cat.

Um exemplo melhor seria o { cut -f2 -d, file1; cut -f1 -d, file2; } | paste -d,que não funciona conforme o esperado.

Com

file1:
a,b
c,d

file2:
1,2
3,4

A produção esperada é:

b,1
d,3

RESOLVIDO:

Use substituição de processo :cat <(command1) <(command2)

Como alternativa, faça pipes nomeados usando mkfifo:

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

Menos elegante e mais detalhado, mas funciona bem, desde que você garanta que temp1 e temp2 não existam antes.

goweon
fonte
11
Isso me faz coçar a cabeça. Você quer canalizar dois comandos diferentes para um único gato?
user606723
2
Você sabe que "canalização" e "argumentos" são dois conceitos completamente independentes, certo?
Ignacio Vazquez-Abrams
@ Ignacio err ... Eu não estou tão familiarizado com o Linux, então eu realmente não sei a diferença. Eu sempre pensei que tubulação significava que leva o resultado anterior como argumento. Gostaria de me esclarecer?
goweon
@firebat no, pipe significa tomar o stdout do comando anterior como entrada padrão do próximo comando. Você ainda pode ter argumentos, que são um conceito diferente.
Rich Homolka
Além disso, no texto da atualização, a saída vem de cat, apenas você deseja que as instruções pareçam separadas para cat, o que não pode ser feito, pois são serializadas em um fluxo.
Rich Homolka

Respostas:

17

Eu acho que você deseja 'Substituição de Processo' http://tldp.org/LDP/abs/html/process-sub.html . Também funciona no zsh, embora tenha mais opções e a sintaxe possa ser diferente.

Ele cria um pseudo arquivo ( /dev/fd/something) para cada substituição. É bem útil. O comando pode ler apenas como um fluxo, o que significa que não pode ir e voltar com o fseek. Ele precisa lê-lo como um fluxo de bytes, como um tubo.

Seus exemplos funcionam como substituição de processo:

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

Pense nisso como uma ferramenta para usar um processo e faça com que ele finja ser um arquivo sem nenhum arquivo temporário.

(da minha resposta anterior )

Rich Homolka
fonte
2

O aparelho cacheado realmente funcionou porque o operador do tubo conectará as saídas padrão dos comandos agrupados à entrada padrão do terceiro.

Você pode dizer que a impressão não é do eco executando qualquer comando que não use a entrada padrão; por exemplo { echo 1; echo 2;} | echo 3, imprimirá 3 em oposição a 1 \ n2 \ n3.

No entanto, isso não é o que você queria, porque os dois comandos nos chavetas estão gravando na mesma saída que é como catos resultados. Para gerar dois resultados diferentes para usar como os dois argumentos para comandos como paste, você precisará usar um arquivo temporário ou um pipe nomeado.

Você pode usar mktemppara gerar um arquivo temporário exclusivo ou mkfifopara criar um arquivo de canal FIFO.

billc.cn
fonte
Um grande obrigado pela sua resposta. Procurei muitos dias por esta solução e finalmente encontrei sua resposta aqui.
Saeed Falsafin
2

Eu gosto do xargs Como exemplo, quero encontrar o tamanho de todos os diretórios de dados do mysql em / usr / local

osx: usuário local $ pwd
/ usr / local
osx: usuário local $ 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: usuário local $ 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: usuário local $ 

xargs

dab
fonte