79

Hat in Linux-Bash etwas ähnlich den folgenden Code in PHP existiert:Linux-Bash: Mehrere variable Zuordnung

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

heißen Sie in einem Satz einen entsprechenden Wert zu 3 verschiedenen Variablen zuweisen.

Nehmen wir an, ich habe die Bash-Funktion myBashFuntion, die auf die Zeichenfolge "qwert asdfg zxcvb" schreibt. Ist es möglich, wie etwas zu tun:

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

Der Teil auf der linken Seite des Gleichheitszeichens ist nicht gültig Syntax natürlich. Ich versuche nur zu erklären, wonach ich frage.

Was funktioniert, obwohl, ist die folgende:

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

Aber ein indiziertes Array ist nicht so ausführlich wie Klarvariablennamen.
aber ich konnte einfach tun:

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

Aber das sind 3 weitere Aussagen, die ich zu vermeiden bevorzugen würden.

Ich bin nur auf der Suche nach einer Abkürzung Syntax. Ist es möglich?

Antwort

152

Das erste, was mir in den Sinn kommt:

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

ausgegeben wird, wenig überraschend

1|2|3 
+0

Wieso habe ich vorher nicht daran gedacht. Danke – GetFree

+1

Danke sehr einfach und interistierend. – pharaoh

+0

Das ist, was ich suche, liebe SO so viel, ;-) – Alcott

0

Kapitel 5 des Bash Cookbook von O'Reilly, diskutiert (mit einiger Ausführlichkeit) die Gründe für die Voraussetzung in einer Variablenzuordnung, dass keine Leerzeichen um das '=' - Zeichen stehen

Die Erklärung hat etwas damit zu tun, zwischen dem Namen eines Befehls und einer Variablen zu unterscheiden (wobei '=' ein gültiges Argument sein kann).

Dies alles scheint ein wenig wie rechtfertigen nach dem Ereignis, aber in keinem Fall wird eine Methode der Zuordnung zu einer Liste von Variablen erwähnt.

+0

Ja, ich weiß. Ich habe hier nur extra Leerzeichen hinzugefügt, um die Lesbarkeit zu verbessern. – GetFree

+0

Ja, das stimmt: readbiity leidet wirklich unter Bash-Skripten. – pavium

4

Ich denke, das helfen könnte ...

Um Benutzer zu brechen eingegeben Daten (mm/tt /) in meiner Skripte, speichere ich den Tag, den Monat und das Jahr in eine Reihe, und dann setze die Werte in separate Variablen wie folgt:

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

Manchmal muss man etwas funky tun. Nehmen wir an, Sie möchten von einem Befehl lesen (das Datumsbeispiel von SDGuero zum Beispiel), aber Sie möchten mehrere Gabeln vermeiden.

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

Sie könnten auch über die Pipeline in den Lesebefehl, aber dann würden Sie die Variablen innerhalb einer Subshell verwenden müssen:

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 

Ergebnisse in ...

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

Der 'read'-Befehl kommt aufgrund der geschweiften Klammern nicht in einer Subshell vor, weil Sie den Lesebefehl auf der rechten Seite der Pipe haben. Sie müssen den 'read'-Befehl in der aktuellen Shell ausführen, was Sie tun können wie' lesen Tag Monat Jahr <<< \ 'Datum" +% d% m% Y "\' ' – pneumatics

+0

Nein - das' lesen' _happens_ aber der Umfang der Variablen, in die er gelesen wird, fällt nicht in den Geltungsbereich, wenn die Subshell der Pipeline endet. – Otheus

+0

Mein Kommentar war über den Grund _why_ das Lesen geschieht in einer Subshell, und ich realisiere jetzt, dass ich falsch gelesen habe, was Sie geschrieben haben. Ich dachte, du meintest, dass die Subshell erstellt wurde, weil du die geschweiften Klammern um die zusammengesetzte Anweisung benutzt hast. Aber! Der Grund, warum du dieses Beispiel gegeben hast, war das Vermeiden von Gabelung, und wird sich die Subshell-Gabel auch nicht verzweigen? – pneumatics

12

Ich wollte die Werte einem Array zuweisen. Also, Michael Krelin Ansatz erstreckt, ich tat:

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

, die ergibt:

2|4|6 

wie erwartet.

+2

Um die Werte in ein Array zu setzen, gibt es bereits eine einfache Lösung, die ich in der Frage erwähnt habe: 'a = ($ (echo 2 4 6)); echo $ {a [0]} $ {a [1]} $ {a [2]} ' – GetFree

+0

Ja, das hatte ich übersehen. Ich würde jedoch argumentieren, dass mein Vorschlag besser geeignet ist, größere Arrays zuzuweisen. – soundray

+0

@soundray Ihre Lösung verwendet eine Erweiterung und eine Herestring, Bash ist was es ist Ich bezweifle, dass es in diesem Szenario gut funktioniert (aber ich habe nicht überprüft). –