Verkettung von Bash-Strings zum Erstellen einer Parameterliste


12

Angesichts dieser Bash:

PARMS='-rvu'
PARMS+=" --delete --exclude='.git'"
echo $PARMS
rsync ${PARMS} . ${TARGET}

Das Echo zeigt die PARMS-Zeichenfolge wie erwartet an, es wird kein Fehler angezeigt, aber rsync verhält sich im Hintergrund so, als ob die mit + = hinzugefügten Optionen nicht vorhanden wären. Dies funktioniert jedoch wie erwartet:

PARMS='-rvu'
rsync ${PARMS} --delete --exclude='.git' . ${TARGET}

Ich glaube, ich habe etwas mit Bash-Anführungszeichen vermasselt (hatte immer Probleme damit), bin mir aber nicht ganz sicher, was und warum die Optionen ignoriert werden, obwohl die Zeichenfolge anscheinend korrekt erstellt wurde.


1
echo "$PARMS"und rsync "${PARMS}"...
Jasonwryan

Dies funktioniert bei mir mit der bashVersion 4.2.25 ohne Änderungen.
Anthon

Antworten:


17

Es gibt einen Unterschied zwischen:

PARMS+="... --exclude='.git'"

und

... --exclude='.git'

Im ersten Fall handelt es sich bei den einfachen Anführungszeichen um innere Anführungszeichen, sodass sie im ersetzten Text, der rsyncals Argumente angegeben wird, buchstäblich vorkommen . rsyncbekommt ein Argument dessen Wert ist --exclude='.git'. In der zweiten werden die einzelnen Anführungszeichen von der Shell zum Zeitpunkt des Schreibens interpretiert, da sie nicht in Anführungszeichen stehen und rsynczu sehen sind --exclude=.git.

In diesem Fall brauchen Sie die einfachen Anführungszeichen überhaupt nicht - es .githandelt sich um ein vollständig gültiges Shell-Wort ohne Sonderzeichen, sodass Sie es wörtlich im Befehl verwenden können.

Besser für diese Art von Dingen ist jedoch ein Array :

PARMS=(-rvu)
PARMS+=(--delete --exclude='.git')
rsync "${PARMS[@]}"

Dies baut Ihren Befehl als separate Wörter auf, wobei die zu interpretierenden Anführungszeichen zum Zeitpunkt des Schreibens der Array-Zeile verwendet werden. "${PARMS[@]}"Erweitert jeden Eintrag im Array als separates Argument, auch wenn das Argument selbst Sonderzeichen oder Leerzeichen enthält. Sie sehen also rsync, was Sie geschrieben haben, wie Sie es gemeint haben.


bashWortteilung durchgeführt, nachdem ${PARMS}erweitert wurde. Das einfache Anführungszeichen wurde also auch von der Shell interpretiert.
Dienstag,

2
Versuch es! Ich tat. Die Anführungszeichen bleiben erhalten, und wenn sich Leerzeichen dazwischen befanden, sind sie ohnehin Teilungspunkte.
Michael Homer

@Gnouc: Von der bash man - Seite: „Quote Ausbau: Nach den vorangegangenen Erweiterungen, alle unquoted Vorkommen der Zeichen \ , 'und ". , Die nicht aus einem der oben genannten Erweiterungen geführt haben entfernt werden“ "über Erweiterungen" beinhaltet Parametererweiterung, die die Erweiterung von ausführt ${PARMS}.
Camh

Vielen Dank. Ich verstehe also, dass in diesem Fall das Weglassen der einfachen Anführungszeichen in den doppelten der Vollständigkeit halber funktionieren wird - was wäre, wenn ich einige Sonderzeichen zitieren müsste und Ihren letzteren Ansatz nicht verwenden wollte?
Neuviemeporte

Wenn Ihre Sonderzeichen nicht Teil von IFS(im Allgemeinen Leerzeichen) sind, müssen Sie sie nicht in Anführungszeichen setzen. Wenn evaldies der Fall ist , haben Sie Pech, es sei denn, Sie hacken etwas zusammen mit - dies ist im Allgemeinen ein Misserfolg, und Arrays sind der richtige Weg, damit umzugehen.
Michael Homer

2

Neben @ Michael Homers Antwort , können Sie bash Funktion eval :

PARMS='-rvu'
PARMS+=" --delete --exclude='.git'"
echo "$PARMS"
eval "rsync ${PARMS} . "'"${TARGET}"'

2
Sie können, aber Sie sollten nicht. Arrays wurden speziell hinzugefügt , um diese Verwendung von zu vermeiden eval.
Chepner
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.