Como concatenar stdin e uma string?

108

Como concatenar stdin a uma string, assim?

echo "input" | COMMAND "string"

e pegue

inputstring
Noam Ross
fonte

Respostas:

119

Um pouco hacky, mas esta pode ser a maneira mais curta de fazer o que você perguntou na pergunta (use um pipe para aceitar stdoutde echo "input"como stdinpara outro processo / comando:

echo "input" | awk '{print $1"string"}'

Resultado:

inputstring

Que tarefa você está tentando realizar exatamente? Mais contexto pode direcionar você para uma solução melhor.

Atualizar - respondendo ao comentário:

@NoamRoss

A maneira mais idiomática de fazer o que você quer é:

echo 'http://dx.doi.org/'"$(pbpaste)"

A $(...)sintaxe é chamada de substituição de comando . Resumindo, ele executa os comandos incluídos em um novo subshell e substitui sua stdoutsaída por onde $(...)foi invocado no shell pai. Então você obteria, de fato:

echo 'http://dx.doi.org/'"rsif.2012.0125"
Sampson-Chen
fonte
1
Obrigado! Isso funciona muito bem. A tarefa exata que estou tentando realizar é pegar uma string da área de transferência (um DOI) e acrescentar um URL a ela, então com isso eu faço pbpaste | awk '{print "http://dx.doi.org/"$1}'e obtenhohttp://dx.doi.org/10.1098/rsif.2012.0125
Noam Ross
5
@sampson-chen, eu usaria '{print $0"string"}'para pegar a coisa toda.
Roman Newaza
3
Na verdade, é anexado stringa cada linha. Experimente echo 'input'\n'another line' | awk '{print $0"string"}'.
tomekwi
55

use cat -para ler de stdin e colocá-lo $()para descartar a nova linha final

echo input | COMMAND "$(cat -)string"

No entanto, por que você não solta o tubo e pega a saída do lado esquerdo em uma substituição de comando:

COMMAND "$(echo input)string"
glenn jackman
fonte
1
Aqui está um exemplo prático: find ~ / other_program / lib -name "* .jar" | tr '\ n' ':' | echo "$ (cat -) ~ / java_app / classes"
Ashwin Jayaprakash
2
Isso funciona para mim no bash, mas no zsh recebo "cat: -: Erro de entrada / saída". Alguma ideia sobre o que poderia causar isso?
Jaymmer - Reintegrar Monica em
"COMMAND" significa a solução e "eco input" para alguns processos mais complicados. O arg "-" para cat só é necessário se houver outros args de arquivo, caso contrário, é o padrão. Então, o que você quis dizer foi: entrada de eco | echo $ (cat) string
Denis Howe
46

Costumo usar pipes, então essa tende a ser uma maneira fácil de prefixar e sufocar stdin:

echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix
rupert160
fonte
2
Obrigado! Na verdade, é um exemplo muito legal de como usar pipeecat
Alex Ivasyuv
1
Esta deve ser a melhor resposta
Chris Koston
1
Por que não apenas echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix":? Ou, a versão mais legível:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax
1
@MiniMax Como a resposta funciona bem com streams, ela funcionará para stdin grande.
anishpatel
1
@anishpatel Minha versão funcionará com stdin grande também. Sem diferença.
MiniMax
11

Você pode fazer isso com sed:

seq 5 | sed '$a\6'
seq 5 | sed '$ s/.*/\0 6/'

No seu exemplo:

echo input | sed 's/.*/\0string/'
Vytenis Bivainis
fonte
9

Existem algumas maneiras de fazer isso, eu pessoalmente acho que a melhor é:

echo input | while read line; do echo $line string; done

Outra pode ser substituindo "$" (caractere de fim de linha) por "string" em um comando sed:

echo input | sed "s/$/ string/g"

Por que eu prefiro o primeiro? Porque ele concatena uma string para stdin instantaneamente, por exemplo, com o seguinte comando:

(echo input_one ;sleep 5; echo input_two ) | while read line; do echo $line string; done

você obtém imediatamente a primeira saída:

input_one string

e depois de 5 segundos você obtém o outro eco:

input_two string

Por outro lado, usando "sed" primeiro ele executa todo o conteúdo do parêntese e depois dá para "sed", então o comando

(echo input_one ;sleep 5; echo input_two ) | sed "s/$/ string/g"

irá imprimir ambas as linhas

input_one string
input_two string

após 5 segundos.

Isso pode ser muito útil nos casos em que você está realizando chamadas para funções que levam muito tempo para serem concluídas e deseja ser continuamente atualizado sobre a saída da função.

Simone
fonte
Na verdade, a opção sed também processa todas as linhas de entrada instantaneamente.
tomekwi
Para uma única linha de entrada, a solução mais simples é a entrada de eco | (leia v; echo $ {v} string) Isso é puro shell, portanto, não requer nenhum processo extra como o sed.
Denis Howe
7

Eu sei que isso está alguns anos atrasado, mas você pode fazer isso com a opção xargs -J:

echo "input" | xargs -J "%" echo "%" "string"

E como é xargs, você pode fazer isso em várias linhas de um arquivo de uma vez. Se o arquivo 'nomes' tiver três linhas, como:

Adam
Bob
Charlie

Você poderia fazer:

cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"
user2635263
fonte
1
Parece legal, exceto -Jque não parece ser padrão / comum. No Linux (de onde xargsestá parte GNU findutils), recebo o erro: Em xargs: invalid option -- 'J'qual sistema isso está?
arielf
3
-Jé para a versão Mac. Para Linux -Iexecuta a mesma função.
user2635263
1
Obrigado! muito útil. Observe que no Linux, esta versão simplificada funciona tão bem: cat names | xargs -I% echo "I like % because he is nice"IOW: não há necessidade de -n 1( xargschamadas echouma vez por linha de entrada de qualquer maneira, pois -Iimplica -L1). Além disso, todas as citações de argumentos separadas parecem ser redundantes.
arielf
3

O comando postado pegaria a string "input" e a usaria como fluxo stdin de COMMAND, o que não produziria os resultados que você está procurando, a menos que COMMAND primeiro imprimisse o conteúdo de seu stdin e depois imprimisse seus argumentos de linha de comando.

Parece que o que você quer fazer está mais próximo da substituição de comandos.

http://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html#Command-Substitution

Com a substituição de comando, você pode ter uma linha de comando como esta:

echo input `COMMAND "string"`

Isso avaliará primeiro COMMAND com "string" como entrada e, em seguida, expandirá os resultados da execução dos comandos em uma linha, substituindo o que está entre os caracteres '`'.

Max DeLiso
fonte
e, claro, @NaomRoss, a menos que seja necessário usar o Bourne shell ou tenha outros mandatos malucos de "portabilidade", você usará a substituição de comando moderna como echo input $(COMMAND "string"), em vez de crases. Boa sorte a todos.
shellter
1

gato será minha escolha: ls | cat - <(echo new line)

Clarkttfu
fonte
sed é um comando baseado em linha que não funciona se o pipe upstream não tiver saída ..
clarkttfu
0

Também funciona:

seq -w 0 100 | xargs -I {} echo "string "{}

Gerará strings como:

string 000
string 001
string 002
string 003
string 004

...

cy8g3n
fonte