2012-04-11 6 views
0

Ich habe ein Bash-Skript, das ein anderes Bash-Skript aufruft. Das aufgerufene Skript führt einige Änderungen und Überprüfungen einiger Dinge durch, verschiebt und übergibt dann den Rest der Befehlszeile des Aufrufers.Parameterliste mit doppelten Anführungszeichen wird nicht richtig in Bash übergeben

In dem aufgerufenen Skript habe ich überprüft, dass ich alles verwaltet habe und bereit zu rufen. Hier einige Debug-Stil Code, den ich in gesteckt haben:

echo $SVN $command [email protected] > /tmp/shimcmd 
bash /tmp/shimcmd 
$SVN $command [email protected] 

nun in/tmp/shimcmd Sie werden sehen:

svn commit --username=myuser --password=mypass --non-interactive --trust-server-cert -m "Auto Update autocommit Wed Apr 11 17:33:37 CDT 2012" 

Das heißt, der eingebaute Befehl, alle auf einer Linie, völlig in Ordnung, einschließlich einer -m "meine Schnur mit Leerzeichen" Teil.

Es ist perfekt. Und die Ausführung "bash/tmp/shimcmd" funktioniert auch perfekt.

Aber natürlich will ich nicht diese alberne tmp-Datei und so (nur zum Debuggen verwendet). Das Problem besteht darin, dass dem Aufruf des Befehls direkt, anstatt über die Shim-Datei:

$SVN $command [email protected] 

Ergebnisse im SVN-Befehl selbst nicht die Zeichenfolge in Anführungszeichen mit Leerzeichen empfangen - es garbles die ‚-m‚meine Zeichenfolge mit Leerzeichen‘ 'Parameter und shanks den Befehl, als ob es übergeben wurde als' -m meine Zeichenfolge mit Leerzeichen '.

Ich habe alle Arten von verrückten Fluchtmethoden vergeblich versucht. Ich kann nicht glauben, dass es mich so schlimm trifft. Wenn Sie das Gleiche ($ SVN $ command $ @) in einer Datei wiederholen und diese Datei dann ausführen, ist es FINE. Aber das Aufrufen von direkt verzerrt die Zeichenfolge in Anführungszeichen. Dieses Element allein schießt.

Irgendwelche Ideen?

Dan

+0

Können Sie einige genaue Schritte Post dieses Verhalten zu bekommen? Ich habe Probleme, das Problem zu reproduzieren. – jimw

+0

@jimw es ist eine sehr häufige Antipattern - im Grunde können Sie nicht auf String-Splitting zählen, um das Richtige zu tun; Er sollte stattdessen Arrays verwenden. –

+0

Sehr wahr.Normalerweise kann ich diese Zitate durch Fiedeln herausholen, aber du hast absolut recht, wenn wir über gute Programmierpraxis sprechen. Ich muss zugeben, wenn ich in meinem Bash-Skript auf Arrays angewiesen bin, wende ich mich normalerweise Perl oder Python zu. – jimw

Antwort

0

Haben Sie versucht:

eval "$SVN $command [email protected]" 

?

+0

Presto! Einfach "eval" hinzufügen: eval "$ SVN $ command $ @" hat es geschafft. Funktioniert genau richtig! Vielen Dank für all die Ideen - werde mit dem simplen eval auf git-er-fertig gehen. – Danimo

+1

@ user1327769 BITTE DAS NICHT TUN. Eval ist sehr unsicher, wenn es um nicht vertrauenswürdige Eingaben geht, während die Verwendung von Arrays diese Fälle sicher behandelt. Siehe http://mywiki.wooledge.org/BashFAQ/048 –

+0

Das obige funktioniert in jeder POSIX-konformen Shell. Die Grundidee dieses Problems besteht darin, dass ein Befehl ausgeführt wird, der über verschiedene Variablen hinweg gespeichert wird. Wenn Sie dem Inhalt dieses Befehls nicht vertrauen, ist dieser ganze Ansatz falsch. Z.B. Wenn jemand '$ SVN' so manipulieren könnte, dass er' rm -rf/'(und Sie sind root), dann wird die Vermeidung von eval Ihnen nicht helfen. – Kaz

0

Hier ist ein Weg, das Problem zu demonstrieren:

$ args='-m "foo bar"' 
$ printf '<%s> ' $args 
<-m> <"foo> <bar"> 

Und hier ist ein Weg, es zu vermeiden:

$ args=(-m "foo bar") 
$ printf '<%s> ' "${args[@]}" 
<-m> <foo bar> 

In diesem letzteren Fall ist args ein Array ist, nicht eine Zeichenfolge in Anführungszeichen.

Beachten Sie übrigens, dass es sein muss "[email protected]", nicht [email protected], um dieses Verhalten zu erhalten (in denen String-Splitting zugunsten der Grenzen der Array-Einträge vermieden wird).

0

diese

echo -n -e $SVN \"$command\" > /tmp/shimcmd 
for x in "[email protected]" 
    do 
    a=$a" "\"$x\" 
    done 
echo -e " " $a >> /tmp/shimcmd 
bash /tmp/shimcmd 

oder einfach

$SVN "$command" "[email protected]" 
+0

Wenn Sie sicher eine Zeichenfolge entkommen möchten, ist 'printf% q 'der kanonische Weg, anstatt ein Chaos von Spaghetti wie folgt zu schreiben. –

+0

Sicher, für Werte von "canonical" nicht gleich "portable" oder "POSIX-Standard". Es kann ein bequemer Weg sein, oder ein GNU-y-Weg, aber kanonisch ist etwas von einem geladenen Wort. – Kaz

Verwandte Themen