Come concatenare stdin e una stringa?


108

Come concatenare stdin a una stringa, in questo modo?

echo "input" | COMMAND "string"

e prendi

inputstring

Risposte:


119

Un po 'hacky, ma questo potrebbe essere il modo più breve per fare ciò che hai chiesto nella domanda (usa una pipe per accettare stdoutda echo "input"come stdina un altro processo / comando:

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

Produzione:

inputstring

Quale compito stai cercando di svolgere esattamente? Un contesto più ampio può darti più indicazioni su una soluzione migliore.

Aggiorna - risposta al commento:

@NoamRoss

Il modo più idiomatico di fare ciò che vuoi è quindi:

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

La $(...)sintassi è chiamata sostituzione dei comandi . In breve, esegue i comandi racchiusi in una nuova subshell e sostituisce il suo stdoutoutput nel punto in cui è $(...)stato invocato nella shell genitrice. Quindi otterrai, in effetti:

echo 'http://dx.doi.org/'"rsif.2012.0125"

1
Grazie! Funziona alla grande. Il compito esatto che sto cercando di realizzare è prendere una stringa dagli appunti (un DOI) e anteporre un URL ad essa, quindi con questo lo faccio pbpaste | awk '{print "http://dx.doi.org/"$1}'e ottengohttp://dx.doi.org/10.1098/rsif.2012.0125
Noam Ross

5
@ sampson-chen, userei '{print $0"string"}'per afferrare l'intera cosa.
Roman Newaza

3
In realtà si aggiunge stringa ogni riga. Prova echo 'input'\n'another line' | awk '{print $0"string"}'.
tomekwi

55

usa cat -per leggere da stdin e inseriscilo $()per buttare via la nuova riga finale

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

Tuttavia, perché non lasci cadere il tubo e prendi l'output del lato sinistro in una sostituzione di comando:

COMMAND "$(echo input)string"

1
Ecco un esempio pratico: trova ~ / altro_programma / lib -name "* .jar" | tr '\ n' ':' | echo "$ (cat -) ~ / java_app / classes"
Ashwin Jayaprakash

2
Questo funziona per me in bash, ma in zsh ottengo "cat: -: Input / output error". Qualche idea su cosa potrebbe causare questo?
jaymmer - Ripristina Monica il

"COMMAND" sta per la soluzione e "echo input" per un processo più complicato. L'argomento "-" per cat è richiesto solo se ci sono altri file arg, altrimenti è l'impostazione predefinita. Quindi quello che intendevi era: echo input | echo $ (cat) string
Denis Howe

46

Uso spesso pipe, quindi questo tende ad essere un modo semplice per aggiungere un prefisso e un suffisso allo stdin:

echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix

2
Grazie! Questo è in realtà un esempio molto interessante di utilizzo pipeecat
Alex Ivasyuv

1
Questa dovrebbe essere la risposta migliore
Chris Koston il

1
Perché non solo echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix":? Oppure, la versione più leggibile:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax

1
@MiniMax Poiché la risposta funziona bene con i flussi, funzionerà per stdin di grandi dimensioni.
anishpatel

1
@anishpatel La mia versione funzionerà anche per stdin di grandi dimensioni. Nessuna differenza.
MiniMax

11

Puoi farlo con sed:

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

Nel tuo esempio:

echo input | sed 's/.*/\0string/'

9

Ci sono alcuni modi per ottenere ciò, personalmente penso che il migliore sia:

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

Un altro può essere la sostituzione di "$" (carattere di fine riga) con "stringa" in un comando sed:

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

Perché preferisco il primo? Perché concatena istantaneamente una stringa a stdin, ad esempio con il seguente comando:

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

si ottiene subito il primo output:

input_one string

e poi dopo 5 secondi si ottiene l'altro eco:

input_two string

D'altra parte usando "sed" prima esegue tutto il contenuto della parentesi e poi lo dà a "sed", quindi il comando

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

produrrà entrambe le linee

input_one string
input_two string

dopo 5 secondi.

Questo può essere molto utile nei casi in cui si eseguono chiamate a funzioni che richiedono molto tempo per essere completate e si desidera essere continuamente aggiornati sull'output della funzione.


In realtà, l' opzione sed elabora anche ogni riga di input istantaneamente.
tomekwi

Per una singola riga di input, la soluzione più semplice è echo input | (leggi v; echo $ {v} stringa) Questa è pura shell, quindi non richiede processi aggiuntivi come sed.
Denis Howe,

7

So che è in ritardo di alcuni anni, ma puoi farlo con l'opzione xargs -J:

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

E poiché è xargs, puoi farlo su più righe di un file contemporaneamente. Se il file "nomi" ha tre righe, come:

Adam
Bob
Charlie

Potresti fare:

cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"

1
Sembra bello tranne -Jche non sembra essere standard / comune. Su Linux (di cui xargsfa parte GNU findutils) ottengo l'errore: su xargs: invalid option -- 'J'quale sistema si trova?
arielf

3
-Jè per la versione per Mac. Per Linux -Isvolge la stessa funzione.
user2635263

1
Grazie! molto utile. Si noti che su Linux, questa versione semplificata funziona altrettanto bene: cat names | xargs -I% echo "I like % because he is nice"IOW: non c'è bisogno di -n 1( xargschiama comunque echouna volta per riga di input, poiché -Iimplica -L1) Inoltre, tutte le citazioni arg separate sembrano essere ridondanti.
arielf

3

Il comando che hai inviato prenderebbe la stringa "input", usandola come flusso stdin di COMMAND, che non produrrebbe i risultati che stai cercando a meno che COMMAND non stampi prima il contenuto del suo stdin e poi stampi i suoi argomenti della riga di comando.

Sembra che quello che vuoi fare sia più vicino alla sostituzione dei comandi.

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

Con la sostituzione dei comandi puoi avere una riga di comando come questa:

echo input `COMMAND "string"`

Questo prima valuterà COMANDO con "stringa" come input, quindi espanderà i risultati dell'esecuzione di tale comando su una riga, sostituendo ciò che è tra i caratteri "" ".


e ovviamente @NaomRoss, a meno che non ti venga richiesto di usare la Bourne shell o di avere altri folli mandati di "portabilità", utilizzerai la moderna sostituzione dei comandi come echo input $(COMMAND "string"), piuttosto che i backtick. Buona fortuna a tutti.
bombardamento del

1

gatto sarà la mia scelta: ls | cat - <(echo new line)


sed è un comando basato su riga che non funziona se il pipe upstream non ha alcun output ..
clarkttfu

0

Funziona anche:

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

Genererà stringhe come:

string 000
string 001
string 002
string 003
string 004

...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.