Capture de la sortie de plusieurs lignes dans une variable Bash

j'ai un script 'myscript' qui sort ce qui suit:

abc
def
ghi

dans un autre script, j'appelle:

declare RESULT=$(./myscript)

et $RESULT obtient la valeur

abc def ghi

y a-t-il un moyen de stocker le résultat soit avec les nouvelles lignes, soit avec le caractère 'n' Pour que je puisse le sortir avec ' echo -e '?

454
demandé sur codeforester 2009-03-05 07:32:18

6 réponses

en fait, le résultat contient ce que vous voulez-pour démontrer:

echo "$RESULT"

ce que vous montrez est ce que vous obtenez de:

echo $RESULT

comme indiqué dans les commentaires, la différence est que (1) la version double-Cité de la variable ( echo "$RESULT" ) préserve l'espacement interne de la valeur exactement comme elle est représentée dans la variable-nouvelles lignes, onglets, blancs multiples et tout - tandis que (2) la version non-Citée ( echo $RESULT ) remplace chaque séquence d'un ou de plusieurs blancs, onglets et nouvelles lignes par un seul espace. Ainsi (1) préserve la forme de la variable d'entrée, tandis que (2) crée une ligne de sortie potentiellement très longue avec des "mots" séparés par des espaces simples (où un " mot " est une séquence de caractères non-blancs; il n'y a pas besoin d'être alphanumérique dans aucun des mots).

850
répondu Jonathan Leffler 2014-08-04 20:33:02

un autre écueil avec ceci est que substitution de commande - $() - bandes traînantes newlines. Probablement pas toujours important, mais si vous voulez vraiment préserver exactement ce qui était sortie, vous devrez utiliser une autre ligne et quelques citations:

RESULTX="$(./myscript; echo x)"
RESULT="${RESULTX%x}"

Ceci est particulièrement important si vous voulez gérer tous noms de fichiers possibles (pour éviter indéfini comportement comme de l'exploitation sur le mauvais fichier).

78
répondu l0b0 2013-12-29 18:00:05

en plus de la réponse donnée par @l0b0 j'ai juste eu la situation où j'avais besoin à la fois de garder n'importe quelle sortie newlines arrière par le script et vérifier le code de retour du script. Et le problème avec la réponse de l0b0 est que l'écho x réinitialisait $? de retour à zéro... j'ai donc réussi à trouver cette solution très astucieuse:

RESULTX="$(./myscript; echo x$?)"
RETURNCODE=${RESULTX##*x}
RESULT="${RESULTX%x*}"
14
répondu Lurchman 2013-07-11 13:03:29

dans le cas où vous êtes intéressé par des lignes spécifiques, utilisez un tableau de résultats:

declare RESULT=($(./myscript))  # (..) = array
echo "First line: ${RESULT[0]}"
echo "Second line: ${RESULT[1]}"
echo "N-th line: ${RESULT[N]}"
12
répondu user2574210 2013-07-11 20:28:45

Comment à propos de cela, il lira chaque ligne à une variable et qui peut être utilisé par la suite ! disons que la sortie myscript est redirigée vers un fichier appelé myscript_output

awk '{while ( (getline var < "myscript_output") >0){print var;} close ("myscript_output");}'
0
répondu Rahul Reddy 2012-05-21 14:21:08

après avoir essayé la plupart des solutions ici, la chose la plus facile que j'ai trouvé était l'évidence - en utilisant un fichier temporaire. Je ne suis pas sûr de ce que vous voulez faire avec votre sortie de ligne multiple, mais vous pouvez ensuite traiter avec elle ligne par ligne en utilisant la lecture. La seule chose que vous ne pouvez pas vraiment faire est facilement coller le tout dans la même variable, mais pour la plupart des fins pratiques, c'est plus facile à traiter.

./myscript.sh > /tmp/foo
while read line ; do 
    echo 'whatever you want to do with $line'
done < /tmp/foo

Rapide hack pour faire l'action demandée:

result=""
./myscript.sh > /tmp/foo
while read line ; do
  result="$result$line\n"
done < /tmp/foo
echo -e $result

Note Ceci ajoute une ligne supplémentaire. Si vous travaillez dessus, vous pouvez coder autour de lui, je suis juste trop paresseux.


EDIT: alors que ce cas fonctionne parfaitement bien, les gens qui lisent ceci devraient être conscients que vous pouvez facilement écraser votre stdin à l'intérieur de la boucle while, vous donnant ainsi un script qui exécutera une ligne, clear stdin, et exit. Comme si ssh allait faire ce que je pense? Je l'ai vu récemment, d'autres exemples de code ici: https://unix.stackexchange.com/questions/24260/reading-lines-from-a-file-with-bash-for-vs-while

encore une fois! Cette fois avec un autre filehandle (stdin, stdout, stderr sont 0-2, donc nous pouvons utiliser &3 ou plus haut en bash).

result=""
./test>/tmp/foo
while read line  <&3; do
    result="$result$line\n"
done 3</tmp/foo
echo -e $result

vous pouvez également utiliser mktemp, mais ce n'est qu'un exemple de code rapide. Utilisation pour mktemp ressemble à:

filenamevar=`mktemp /tmp/tempXXXXXX`
./test > $filenamevar

alors utilisez $ filenamevar comme vous le feriez le nom réel d'un fichier. Probablement n'a pas besoin d'être expliqué ici, mais quelqu'un s'est plaint dans les commentaires.

-1
répondu user1279741 2017-04-13 12:36:28