79

existe dans bash linux quelque chose de similaire au code suivant en PHP:bash Linux: affectation de variables multiples

list($var1, $var2, $var3) = function_that_returns_a_three_element_array() ; 

dire que vous attribuez dans une phrase une valeur correspondant à 3 variables différentes. Disons que j'ai la fonction bash myBashFuntion qui écrit dans stdout la chaîne "qwert asdfg zxcvb". Est-il possible de faire quelque chose comme:

(var1 var2 var3) = (`myBashFuntion param1 param2`) 

La partie à gauche du signe égal n'est pas une syntaxe valide bien sûr. J'essaie juste d'expliquer ce que je demande.

Qu'est-ce que le travail, cependant, est la suivante:

array = (`myBashFuntion param1 param2`) 
echo ${array[0]} ${array[1]} ${array[2]} 

Mais un tableau indexé n'est pas aussi descriptif que les noms de variables simples.
Cependant, je pouvais faire:

var1 = ${array[0]} ; var2 = ${array[1]} ; var3 = ${array[2]} 

Mais ce sont 3 autres déclarations que je préfèrerais éviter.

Je cherche juste une syntaxe de raccourci. C'est possible?

Répondre

152

La première chose qui me vient à l'esprit:

read -r a b c <<<$(echo 1 2 3) ; echo "$a|$b|$c" 

sortie est, sans surprise

1|2|3 
+0

Comment ça se fait que je n'y ai pas pensé avant. Merci – GetFree

+1

Merci très simple et interessant. – pharaoh

+0

C'est ce que je cherche, tant d'amour, tellement ;-) – Alcott

0

Chapitre 5 du Bash Cookbook par O'Reilly, discute (longuement) les raisons de la exigence dans une assignation de variable qu'il n'y ait pas d'espaces autour du signe '='

MYVAR="something" 

L'explication a quelque chose à voir avec la distinction entre le nom d'une commande et une variable (où '=' peut être un argument valide).

Tout cela ressemble un peu à une justification après l'événement, mais dans tous les cas il n'y a aucune mention d'une méthode d'affectation à une liste de variables.

+0

Oui, je sais. Je viens d'ajouter des espaces supplémentaires ici et là par souci de lisibilité. – GetFree

+0

Oui, c'est vrai: readbiity souffre vraiment dans les scripts bash. – pavium

4

Je pense que cela pourrait aider ...

Pour décomposer les dates entrées utilisateur (mm/jj/aaaa) dans mes scripts, je stocke le jour, le mois et l'année dans un tableau, puis mettre les valeurs en variables distinctes comme suit:

DATE_ARRAY=(`echo $2 | sed -e 's/\// /g'`) 
MONTH=(`echo ${DATE_ARRAY[0]}`) 
DAY=(`echo ${DATE_ARRAY[1]}`) 
YEAR=(`echo ${DATE_ARRAY[2]}`) 
3

Parfois, vous devez faire quelque chose funky. Disons que vous voulez lire depuis une commande (l'exemple de date par SDGuero par exemple) mais vous voulez éviter plusieurs fourchettes.

read month day year << DATE_COMMAND 
$(date "+%m %d %Y") 
DATE_COMMAND 
echo $month $day $year 

Vous pouvez également tuyau dans la commande de lecture, mais alors vous devez utiliser les variables dans un sous-shell:

day=n/a; month=n/a; year=n/a 
date "+%d %m %Y" | { read day month year ; echo $day $month $year; } 
echo $day $month $year 

résultats dans ...

13 08 2013 
n/a n/a n/a 
+0

La commande 'read' ne se produit pas dans un sous-shell à cause des accolades, c'est parce que vous avez la commande read sur le côté droit du pipe. Vous devez exécuter la commande 'read' dans le shell actuel, ce que vous pouvez faire comme' read jour mois année <<< \ 'date" +% d% m% Y "\' ' – pneumatics

+0

Non - le' lire' _happens_ mais la portée des variables dans lesquelles il se lit tombe hors de la portée lorsque le sous-shell du pipeline se termine. – Otheus

+0

Mon commentaire était sur la raison pour laquelle la lecture se passe dans un sous-shell, et je me rends compte maintenant que j'ai mal lu ce que vous avez écrit. Je pensais que vous vouliez dire que le sous-shell a été créé parce que vous avez utilisé les accolades autour de la déclaration composée. Mais! La raison pour laquelle vous avez donné cet exemple était d'éviter de forger, et ne sera pas la fourchette de sous-couche, aussi? – pneumatics

12

Je voulais attribuer les valeurs à un tableau. Ainsi, pour poursuivre l'approche de Michael Krelin, je l'ai fait:

read a[{1..3}] <<< $(echo 2 4 6); echo "${a[1]}|${a[2]}|${a[3]}" 

qui donne:

2|4|6 

comme prévu.

+2

Pour mettre les valeurs dans un tableau, il existe déjà une solution simple que j'ai mentionnée dans la question: 'a = ($ (echo 2 4 6)); echo $ {a [0]} $ {a [1]} $ {a [2]} ' – GetFree

+0

Oui, j'avais oublié cela. Je dirais, cependant, que ma suggestion est mieux adaptée à l'attribution de tableaux plus grands. – soundray

+0

@soundray Votre solution utilise l'expansion et une fonction, ce qui est ce que je suis, je doute qu'elle fonctionne bien dans ce scénario (mais je n'ai pas vérifié). –

Questions connexes