2013-07-23 19 views
9

Ich versuche, mehrere Zeilen von Shell-Befehle mit eval zu bewerten, aber wenn ich versuche, Variablen mit Eval getrennt durch einen Zeilenumbruch \n aufzulösen die Variablen sind nicht gelöst.Wie mehrere Befehle an eval in Bash übergeben

x='echo a' 
y='echo b' 
z="$x\n$y" 
eval $x 
eval $y 
eval $z 

Welche Ausgänge:

a 
b 
anecho b 

Der letzte Befehl gibt anecho b und anscheinend \n wurde als n dort behandelt. Gibt es also eine Möglichkeit, mehrere Befehlszeilen auszuwerten (zB getrennt durch \n)?

+3

Versuchen Sie, mit ';', nicht '\ n' –

+1

oder mit' && 'zu trennen, wenn Sie sicherstellen möchten, dass der spätere cmd exec wird, wenn der vorherige erfolgreich ausgeführt wurde. – Kent

+0

@Kent '&&' funktioniert nicht, wenn ein vorheriger Befehl unvollständig ist, z. 'x = 'wenn wahr'; y = 'dann echo a; fi'' –

Antwort

8

\n kein newline ist; Es ist eine Escape-Sequenz, die in einigen Situationen in eine neue Zeile übersetzt, aber Sie haben es in einer dieser Situationen nicht verwendet. Die Variable $z wird nicht geschlossen und enthält eine neue Zeile, nur umgekehrter Schrägstrich gefolgt von "n".Als Ergebnis ist das, was tatsächlich ausgeführt hat wird:

$ echo a\necho b 
anecho b 

Sie entweder ein Semikolon stattdessen verwenden können (das keine Übersetzung erfordert) oder \n in einem Kontext verwenden, wo es wird in eine neue Zeile übersetzt werden:

$ newline=$'\n' 
$ x='echo a' 
$ y='echo b' 
$ z="$x$newline$y" 
$ eval "$z" 
a 
b 

Beachten Sie die doppelten Anführungszeichen um "$z" - sie sind tatsächlich kritisch hier. Ohne sie teilt bash den Wert von $z word-split und verwandelt alle Leerzeichen (Leerzeichen, Tabulatoren, Zeilenumbrüche) in Wortumbrüche. Wenn das geschieht, welche die Worte „echo“ „a“ „echo“ b“, effektiv die Newline in einen Raum dreht eval bekommen:

$ eval $z 
a echo b 

Dies ist eine weitere in der langen Liste der Fälle, in denen es wichtig ist, double-quote Variablenreferenzen

+0

ausgezeichnet! Danke für den '$ newline'-Trick und das Erklären der Anführungszeichen –

5

Sie übergeben die neue Zeile in Eval. So ist es, wie Sie auf der Konsole eingeben dies:

[email protected]$ echo a\necho b 
anecho b 

So ist der erste echo richtig verstanden wird, und es denkt, Sie Anführungszeichen um den Rest. Der Backslash scheint ignoriert zu werden. Vielleicht bedeutete Sie so etwas wie dieses:

[email protected]$ echo -e 'a\n'; echo b 
a 

b 

Option 1:

abgrenzen Aussagen in eval übergeben mit einem Semikolon wie folgt aus:

x='echo a' 
y='echo b' 
z="$x;$y" 
eval $x 
eval $y 
eval $z 

druckt:

a 
b 
a 
b 

Option 2:

Setzen Sie das Newline in dem Ort, wo es durch das Echo interpretiert wird, wie folgt aus:

x='echo -e "a\n"' 
y='echo b' 
z="$x;$y" 
eval $x 
eval $y 
eval $z 

druckt:

a 

b 
a 

b 

Jetzt ist das Newline erhalten und durch das Echo interpretiert, nicht das Eval.

3

Nicht unbedingt die optimale Art und Weise, wie es fehlschlägt, wenn das x und y Variablen Sequenzen verarbeitet durch printf wie %s und ähnlichen enthalten, aber wie auch immer, hier ist eine Methode, es zu tun, während \n als Trennzeichen zu halten:

x='echo a' 
y='echo b' 
z="$x\n$y" 
eval $x 
eval $y 
export IFS=" " 
eval $(printf "$z") 

druckt:

a 
b 
a 
b 
0

Auf meiner FreeBSD-Box habe ich versucht, etwas in einem Bourne-Skript zu tun, das zunächst ziemlich trivial erschien - aber meine Gedanken für ein paar Momente trübte .. Seit dieser Seite ist, was ich versucht habe behebe mein Problem, ich werde erklären, was ich tun musste und wie ich es geschafft habe:

a=A 

b=B 

eval ${a}_${b}="something" 

Keine Probleme bisher. Ich bekomme eine neue Variable A_B, die „etwas“

speichert Aber wenn ich den Auftrag über 2 Zeilen wie unter verteilt:

eval ${a}_${b}="some 

thing" 

Die Schale bellt mich an, dass es keinen Befehl finden kann ‚Ding‘ genannt . Es ist wichtig zu verstehen, dass eval versucht, RHS als Befehl zu bewerten. Um EVAL zu erhalten, um RHS als eine Zeichenfolge zu bewerten, müssen Sie RDA doppel-dotieren:

Hope das hilft jemandem. Manish Jain