2014-11-10 8 views
5

ich eine Variable, die ein bisschen wie folgt aussieht:Was ist die POSIX-Shell-Äquivalent von bash <<<

msg="newton apple tree" 

Ich möchte jedes dieser Wörter in einzelne Variablen zugewiesen werden soll. Dies ist einfach in bash:

read a b c <<< $msg 

Gibt es eine kompakte, lesbare Möglichkeit, dies in POSIX-Shell zu tun?

+0

'Bash' steht für 'Bourne Again Shell'. Es ist eine größere, bessere, schnellere Version von 'Bourne Shell'. Also ist es unwahrscheinlich. – Sobrique

+0

Ich weiß nicht, wie * lesbar * du es betrachten würdest, aber es bedeutet, eine Pfeife zu benutzen. Ist das eine Möglichkeit, die Sie bereits abgelehnt haben? – hardmath

+2

Wenn es ein POSIX sh gab (du meinst wahrscheinlich nicht wirklich Bourne - Bourne ist eine Shell aus den 70ern; es sei denn, du bist auf mäßig alten Solaris, niemand hat Bourne) äquivalent, warum hätte bash das einführen müssen? Feature? –

Antwort

8

Um idiomatische Skripte zu schreiben, können Sie nicht nur Blick auf jeden einzelnen Syntaxelement und versuchen um ein POSIX-Äquivalent zu finden. Das ist wie das Übersetzen von Text, indem jedes einzelne Wort durch seinen Eintrag im Wörterbuch ersetzt wird.

Der POSIX-Weg, um eine Zeichenfolge bekannt Aufspalten drei Worte in drei Argumente zu haben, ähnlich, aber nicht identisch mit read ist:

var="newton apple tree" 

set -f 
set -- $var 
set +f 
a=$1 b=$2 c=$3 

echo "$a was hit by an $b under a $c" 
+0

Ich könnte das in einer Funktion arbeiten, um zu vermeiden, das globale '$ @' zu überschreiben, aber das ist eine großartige Lösung. –

+2

Dies überschreibt unnötigerweise die Positionsparameter; Eine Here-Zeichenkette ist hier nur eine Abkürzung für Single-Line-Dokumente, so dass es nicht nötig ist, den 'read' durch den' set'-Befehl zu ersetzen. – chepner

3

Es ist nicht schön, aber als allgemeine Lösung können Sie dies mit einer Named Pipe umgehen.

Von BashFAQ #24:

mkfifo mypipe 
printf '%s\n' "$msg" >mypipe & 
read -r a b c <mypipe 

printf ist zuverlässiger/besser spezifiziert als echo; Das Echoverhalten variiert zwischen Implementierungen, wenn Sie eine Nachricht haben, die nur -E oder -n enthält.


Das heißt, für das, was Sie hier machen, die Sie gerade Parameter Expansion verwenden:

a=${msg%% *}; msg=${msg#* } 
b=${msg%% *}; msg=${msg#* } 
c=${msg%% *}; msg=${msg#* } 
+0

Ich denke, Sie müssen "a b c" anstelle von Zeile hinzufügen, um es für mein Beispiel relevanter zu machen. Aber das sieht nach einer möglichen Antwort aus. – Bitdiot

+0

ah, okay, das sieht besser aus. – Bitdiot

+0

Ich möchte Ihnen den Scheck geben, aber ich denke, dass der Typ eine elegantere Lösung hat. Ich hoffe, es macht dir nichts aus. – Bitdiot

10

A hier Saite ist nur syntaktischer Zucker für ein einzeiligen hier Dokument:

$ msg="foo * bar" 
$ read a b c <<EOF 
> $msg 
> EOF 
$ echo "$a" 
foo 
$ echo "$b" 
* 
$ echo "$c" 
bar