Ich habe ein Wrapper-Skript, das einige Arbeiten erledigt und dann die ursprünglichen Parameter an ein anderes Tool weitergibt:
#!/bin/bash
# ...
other_tool -a -b "$@"
Dies funktioniert einwandfrei, es sei denn, das "andere Tool" wird in einer Subshell ausgeführt:
#!/bin/bash
# ...
bash -c "other_tool -a -b $@"
Wenn ich mein Wrapper-Skript so aufrufe:
wrapper.sh -x "blah blup"
dann wird nur das erste ursprüngliche Argument (-x) an "other_tool" übergeben. In Wirklichkeit erstelle ich keine Subshell, sondern übergebe die ursprünglichen Argumente an eine Shell auf einem Android-Handy, was keinen Unterschied machen sollte:
#!/bin/bash
# ...
adb sh -c "other_tool -a -b $@"
Keine der Lösungen funktioniert gut. Übergeben Sie einfach x / \ "b" / aaaaa / "xxx \ yyyy" / zz "offf" als Parameter und sie schlagen fehl.
Hier ist ein einfacher Wrapper, der jeden Fall behandelt. Beachten Sie, wie jedes Argument zweimal umgangen wird.
quelle
Wechseln Sie
$@
zu$*
. Ich habe einen kleinen lokalen Test gemacht und es funktioniert in meinem Fall.Speichern als
test.sh
und ausführbar machen gibtEs gibt einen subtilen Unterschied zwischen
$*
und$@
, wie Sie sehen können. Siehe z. B. http://ss64.com/bash/syntax-parameters.htmlFür die Folgefrage in den Kommentaren: Sie müssen zB Leerzeichen "zweimal" maskieren, um eine Zeichenfolge mit einem Trennzeichen als kombiniertes Argument zu übergeben, z. B. mit
test.sh
einemwc
Wrapper geändert :Das funktioniert:
aber:
quelle
wrapper.sh -x "blah blup"
Dann erhält die Subshell DREI Parameter (-x, bla, blup) anstelle von ZWEI (-x, "bla bla")"Blah\ blup"
. H. Probieren Sie es aus und sehen Sie, ob es funktioniert.Es schlägt fehl, weil Sie ein Array (die Positionsparameter) in eine Zeichenfolge zwingen.
"$@"
ist magisch, weil es Ihnen jeden einzelnen Parameter als richtig zitierte Zeichenfolge gibt. Das Hinzufügen von zusätzlichem Text unterbricht die Magie:"blah $@"
ist nur eine einzelne Zeichenfolge.Dies kann Sie näher bringen:
Natürlich verursacht jeder Parameter, der ein einfaches Anführungszeichen enthält, Probleme.
quelle
Ok, mehr Erklärungen:
quelle
Ich habe viele verschiedene Lösungen ausprobiert. Eine gute Ressource mit Hintergrundinformationen und Alternativen ist beispielsweise BashFAQ / 096 in Gregs (auch bekannt als GreyCats) Wiki . Insgesamt fand ich die folgenden zwei am besten lesbar (von den funktionierenden):
Seit Bash 4.4 (soweit ich aus den NEWS ersehen kann ) ist es möglich, die Parametererweiterung
@Q
wie folgt zu verwenden :Beachten Sie, dass ich
$*
hier anstelle von verwende,$@
weil Sie"other_tool -a -b ${*@Q}"
eine einzelne Zeichenfolge anstelle einer Zeichenfolge pro übergebenem Argument sein möchten .Wenn Sie dasselbe mit einer Bash-Array-Variablen tun möchten, benötigen Sie die Syntax
${ARRAY[*]@Q}
(innerhalb der Anführungszeichen).Wenn Sie Bash 4.4 oder höher nicht verfügbar haben oder sich nicht sicher sind, ist dies meine bevorzugte Lösung:
Beachten Sie, dass Sie hier
"$@"
anstelle von$@
oder"$*"
oder verwenden müssen,$*
weil Sie keine Wortaufteilung innerhalb von Argumenten wünschen, sodass die Varianten ohne Anführungszeichen nicht verwendet werden können und die Anzahl der Argumente beibehalten werden soll, sodass"$*"
sie nicht so verwendet werden können, wie sie sich verbinden würden alle Argumente zu einer einzelnen Zeichenfolge. Die Funktion gibt dann alle Argumente in einer einzelnen Zeichenfolge zurück.Wenn Sie nicht über den zusätzlichen Raum vor dem ersten Argument ist es egal, können Sie das ändern
printf
Formatstring" %q"
und die entfernenseparator
Variable. Oder Sie können den Einzeiler von Gordon Davissons Antwort verwenden .Diese Lösungen funktionieren in allen Fällen, die mir einfallen könnten, insbesondere:
escapeBashArgs
→ nichtsescapeBashArgs "" ""
→'' ''
escapeBashArgs " " " "
→' ' ' '
oder\ \ \ \ \
( das letzte Leerzeichen wird von diesem Site-Renderer gegessen )escapeBashArgs "a b" c\ d "arg with newline"
→'a b' 'c d' $'arg with\nnewline'
odera\ \ \ \ \ \ b c\ d $'arg with\nnewline'
( die Zeilenumbruchstelle befindet sich zwischenwith
undnewline
an anderen Positionen liegt dies am Zeilenumbruch auf dieser Site )escapeBashArgs '$"'\''({:})'
→'$"'\''({:})'
oder\$\"\'\(\{:\}\)
escapeBashArgs x/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
→'x/ "b"/aaaaa/'\''xxx yyyy'\''/zz"offf"'
oderx/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
(Getestet mit GNU Bash 5.0.3 (1) -Release.)
quelle
quelle