¿Cómo concatenar stdin y una cadena?

108

¿Cómo concatenar stdin a una cadena, como esta?

echo "input" | COMMAND "string"

y obten

inputstring
Noam Ross
fuente

Respuestas:

119

Un poco hacky, pero esta podría ser la forma más corta de hacer lo que preguntó en la pregunta (use una tubería para aceptar stdoutdesde echo "input"como stdina otro proceso / comando:

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

Salida:

inputstring

¿Qué tarea estás tratando de realizar exactamente? Más contexto puede brindarle más orientación hacia una mejor solución.

Actualización - respondiendo al comentario:

@NoamRoss

La forma más idiomática de hacer lo que quiere es entonces:

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

La $(...)sintaxis se llama sustitución de comandos . En resumen, ejecuta los comandos incluidos en una nueva subcapa y sustituye su stdoutsalida por donde $(...)se invocó en la shell principal. Entonces obtendría, en efecto:

echo 'http://dx.doi.org/'"rsif.2012.0125"
sampson-chen
fuente
1
¡Gracias! Esto funciona muy bien. La tarea exacta que estoy tratando de lograr es tomar una cadena del portapapeles (un DOI) y anteponer una URL, así que con esto lo hago pbpaste | awk '{print "http://dx.doi.org/"$1}'y obtengohttp://dx.doi.org/10.1098/rsif.2012.0125
Noam Ross
5
@ sampson-chen, solía '{print $0"string"}'agarrarlo todo.
Roman Newaza
3
De hecho, se agrega stringa cada línea. Prueba echo 'input'\n'another line' | awk '{print $0"string"}'.
tomekwi
55

use cat -para leer desde stdin, y colóquelo $()para deshacerse de la nueva línea final

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

Sin embargo, ¿por qué no suelta la tubería y toma la salida del lado izquierdo en una sustitución de comando?

COMMAND "$(echo input)string"
Glenn Jackman
fuente
1
Aquí hay un ejemplo práctico: busque ~ / otro_programa / lib -name "* .jar" | tr '\ n' ':' | echo "$ (cat -) ~ / java_app / classes"
Ashwin Jayaprakash
2
Esto me funciona en bash, pero en zsh obtengo "cat: -: error de entrada / salida". ¿Alguna idea de qué podría causar esto?
jaymmer - Reincorporación a Monica
"COMMAND" significa la solución y "echo input" para un proceso más complicado. El argumento "-" para cat solo es necesario si hay otros argumentos de archivo; de lo contrario, es el predeterminado. Entonces, lo que quisiste decir fue: entrada de eco | echo $ (cat) string
Denis Howe
46

A menudo uso tuberías, por lo que esta suele ser una forma fácil de prefijar y sufijar stdin:

echo -n "my standard in" | cat <(echo -n "prefix... ") - <(echo " ...suffix")
prefix... my standard in ...suffix
rupert160
fuente
2
¡Gracias! Ese es realmente un ejemplo muy bueno de usar pipeycat
Alex Ivasyuv
1
Esta debería ser la mejor respuesta
Chris Koston
1
¿Por qué no simplemente echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix":? O, la versión más legible:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax
1
@MiniMax Debido a que la respuesta funciona bien con transmisiones, funcionará para stdin grandes.
anishpatel
1
@anishpatel Mi versión también funcionará para stdin grandes. Ninguna diferencia.
MiniMax
11

Puedes hacerlo con sed:

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

En tu ejemplo:

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

Hay algunas formas de lograr esto, personalmente creo que la mejor es:

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

Otro puede ser sustituyendo "$" (carácter de fin de línea) con "cadena" en un comando sed:

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

¿Por qué prefiero el primero? Porque concatena una cadena a stdin instantáneamente, por ejemplo con el siguiente comando:

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

obtienes inmediatamente la primera salida:

input_one string

y luego, después de 5 segundos, obtienes el otro eco:

input_two string

Por otro lado usando "sed" primero realiza todo el contenido del paréntesis y luego le da a "sed", entonces el comando

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

dará salida a ambas líneas

input_one string
input_two string

después de 5 segundos.

Esto puede ser muy útil en los casos en que esté realizando llamadas a funciones que demoren mucho en completarse y desee estar actualizado continuamente sobre el resultado de la función.

Simone
fuente
En realidad, la opción sed también procesa cada línea de entrada al instante.
tomekwi
Para una sola línea de entrada, la solución más simple es entrada de eco | (leer v; echo $ {v} cadena) Eso es puro shell por lo que no requiere un proceso adicional como sed.
Denis Howe
7

Sé que esto tiene un retraso de algunos años, pero puede lograrlo con la opción xargs -J:

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

Y como es xargs, puede hacer esto en varias líneas de un archivo a la vez. Si el archivo 'nombres' tiene tres líneas, como:

Adam
Bob
Charlie

Podrías hacerlo:

cat names | xargs -n 1 -J "%" echo "I like" "%" "because he is nice"
usuario2635263
fuente
1
Se ve bien, excepto -Jque no parece ser estándar / común. En Linux (de donde xargsforma parte GNU findutils) aparece el error: xargs: invalid option -- 'J'¿En qué sistema está?
arielf
3
-Jes para la versión Mac. Para Linux -Irealiza la misma función.
user2635263
1
¡Gracias! muy útil. Tenga en cuenta que en Linux, esta versión simplificada funciona igual de bien: cat names | xargs -I% echo "I like % because he is nice"IOW: no es necesario el -n 1( xargsllamadas echouna vez por línea de entrada de todos modos, ya que -Iimplica -L1) Además, todas las citas de arg por separado parecen ser redundantes.
arielf
3

El comando que publicó tomaría la cadena "input" y la usaría como flujo stdin de COMMAND, que no produciría los resultados que está buscando a menos que COMMAND imprima primero el contenido de su stdin y luego imprima sus argumentos de línea de comando.

Parece que lo que quiere hacer está más cerca de la sustitución de comandos.

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

Con la sustitución de comandos, puede tener una línea de comandos como esta:

echo input `COMMAND "string"`

Esto primero evaluará COMMAND con "cadena" como entrada, y luego expandirá los resultados de la ejecución de esos comandos en una línea, reemplazando lo que está entre los caracteres '`'.

Max DeLiso
fuente
y, por supuesto, @NaomRoss, a menos que se le requiera usar el shell Bourne o tener otros mandatos locos de "portabilidad", usará la sustitución de comandos moderna como echo input $(COMMAND "string"), en lugar de comillas inversas. Buena suerte a todos.
Shellter
1

gato será mi elección: ls | cat - <(echo new line)

clarkttfu
fuente
SED es una orden basada línea que no funciona si la tubería aguas arriba tiene ninguna salida ..
clarkttfu
0

También funciona:

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

Generará cadenas como:

string 000
string 001
string 002
string 003
string 004

...

cy8g3n
fuente