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
'?
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).
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).
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*}"
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]}"
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");}'
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.