Comment concaténer stdin et une chaîne?


108

Comment concaténer stdin en une chaîne, comme ça?

echo "input" | COMMAND "string"

et obtenir

inputstring

Réponses:


119

Un peu hacky, mais c'est peut-être le moyen le plus court de faire ce que vous avez demandé dans la question (utilisez un tube pour accepter stdoutde echo "input"comme stdinvers un autre processus / commande:

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

Production:

inputstring

Quelle tâche essayez-vous exactement d'accomplir? Plus de contexte peut vous aider à trouver une meilleure solution.

Mise à jour - réponse au commentaire:

@NoamRoss

La façon la plus idiomatique de faire ce que vous voulez est alors:

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

La $(...)syntaxe est appelée substitution de commande . En bref, il exécute les commandes incluses dans un nouveau sous-shell et substitue sa stdoutsortie à l'endroit où le a $(...)été appelé dans le shell parent. Ainsi, vous obtiendriez, en effet:

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

1
Merci! Cela fonctionne très bien. La tâche exacte que j'essaie d'accomplir est de prendre une chaîne du presse-papiers (un DOI) et d'y ajouter une URL, donc avec cela, je le fais pbpaste | awk '{print "http://dx.doi.org/"$1}'et j'obtienshttp://dx.doi.org/10.1098/rsif.2012.0125
Noam Ross

5
@ sampson-chen, j'utiliserais '{print $0"string"}'pour saisir le tout.
Roman Newaza

3
Il s'ajoute en fait stringà chaque ligne. Essayez echo 'input'\n'another line' | awk '{print $0"string"}'.
tomekwi

55

utilisez cat -pour lire à partir de stdin, et mettez-le $()pour jeter la nouvelle ligne de fin

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

Cependant, pourquoi ne pas laisser tomber le tube et saisir la sortie du côté gauche dans une substitution de commande:

COMMAND "$(echo input)string"

1
Voici un exemple pratique: find ~ / other_program / lib -name "* .jar" | tr '\ n' ':' | echo "$ (cat -) ~ / java_app / classes"
Ashwin Jayaprakash

2
Cela fonctionne pour moi dans bash, mais dans zsh j'obtiens "cat: -: Erreur d'entrée / sortie". Une idée de ce qui pourrait causer cela?
jaymmer - Réintégrer Monica

"COMMAND" représente la solution et "l'entrée écho" pour un processus plus compliqué. L'argument "-" de cat n'est requis que s'il y a d'autres arguments de fichier, sinon c'est la valeur par défaut. Donc, ce que vous vouliez dire était: entrée d'écho | echo $ (cat) string
Denis Howe

46

J'utilise souvent des tubes, donc cela a tendance à être un moyen facile de préfixer et de suffixer stdin:

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

2
Merci! C'est en fait un exemple très cool d'utilisation pipeetcat
Alex Ivasyuv

1
Cela devrait être la meilleure réponse
Chris Koston

1
Pourquoi pas simplement echo "my standard in" | echo -e "prefix\n$(cat -)\nsuffix":? Ou, la version la plus lisible:echo "my standard in" | printf "%s\n%s\n%s\n" "prefix" "$(cat -)" "suffix"
MiniMax

1
@MiniMax Parce que la réponse fonctionne bien avec les flux, elle fonctionnera pour les grands stdin.
anishpatel

1
@anishpatel Ma version fonctionnera aussi pour les grands stdin. Aucune différence.
MiniMax

11

Vous pouvez le faire avec sed:

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

Dans votre exemple:

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

9

Il y a quelques moyens d'y parvenir, je pense personnellement que le meilleur est:

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

Un autre peut être en remplaçant "$" (caractère de fin de ligne) par "string" dans une commande sed:

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

Pourquoi je préfère le premier? Parce qu'il concatène une chaîne à stdin instantanément, par exemple avec la commande suivante:

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

vous obtenez immédiatement la première sortie:

input_one string

puis après 5 secondes, vous obtenez l'autre écho:

input_two string

D'un autre côté, en utilisant "sed", il exécute d'abord tout le contenu de la parenthèse et ensuite il le donne à "sed", donc la commande

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

affichera les deux lignes

input_one string
input_two string

après 5 secondes.

Cela peut être très utile dans les cas où vous effectuez des appels à des fonctions qui prennent beaucoup de temps et que vous souhaitez être continuellement mis à jour sur la sortie de la fonction.


En fait, l' option sed traite également chaque ligne d'entrée instantanément.
tomekwi

Pour une seule ligne d'entrée, la solution la plus simple est l'entrée écho | (lire v; echo $ {v} string) C'est un shell pur donc ne nécessite aucun processus supplémentaire comme sed.
Denis Howe

7

Je sais que cela a quelques années de retard, mais vous pouvez le faire avec l'option xargs -J:

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

Et comme il s'agit de xargs, vous pouvez le faire sur plusieurs lignes d'un fichier à la fois. Si le fichier 'noms' a trois lignes, comme:

Adam
Bob
Charlie

Vous pourriez faire:

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

1
Ça a l'air cool sauf que -Jça ne semble pas être standard / commun. Sous Linux (où xargsfait partie de GNU findutils), j'obtiens l'erreur: Sur xargs: invalid option -- 'J'quel système est-ce?
arielf

3
-Jest pour la version Mac. Pour Linux -Iremplit la même fonction.
user2635263

1
Merci! très utile. Veuillez noter que sous Linux, cette version simplifiée fonctionne aussi bien: cat names | xargs -I% echo "I like % because he is nice"IOW: pas besoin de -n 1( xargsappelle echoune fois par ligne d'entrée de toute façon, puisque l' -Iimplique -L1) De plus, toutes les citations séparées d'arg, semblent redondantes.
arielf

3

La commande que vous avez postée prendrait la chaîne «entrée» l'utiliser comme flux stdin de COMMAND, ce qui ne produirait pas les résultats que vous recherchez à moins que COMMAND n'imprime d'abord le contenu de son stdin, puis imprime ses arguments de ligne de commande.

Il semble que ce que vous voulez faire est plus proche de la substitution de commandes.

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

Avec la substitution de commande, vous pouvez avoir une ligne de commande comme celle-ci:

echo input `COMMAND "string"`

Cela évaluera d'abord COMMAND avec "string" comme entrée, puis étendra les résultats de l'exécution de cette commande sur une ligne, en remplaçant ce qui se trouve entre les caractères '`'.


et bien sûr @NaomRoss, à moins que vous ne soyez obligé d'utiliser Bourne shell ou d'avoir d'autres mandats de «portabilité» fous, vous utiliserez la substitution de commande moderne comme echo input $(COMMAND "string"), plutôt que des contre-indications. Bonne chance à tous.
shellter

1

chat sera mon choix: ls | cat - <(echo new line)


sed est une commande basée sur la ligne qui ne fonctionne pas si le tuyau en amont n'a rien de sortie ..
clarkttfu

0

Fonctionne également:

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

Générera des chaînes comme:

string 000
string 001
string 002
string 003
string 004

...

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.