Mam skrypt otoki, który działa trochę, a następnie przekazuje oryginalne parametry do innego narzędzia:
#!/bin/bash
# ...
other_tool -a -b "$@"
Działa to dobrze, chyba że „inne narzędzie” działa w podpowłoce:
#!/bin/bash
# ...
bash -c "other_tool -a -b $@"
Jeśli wywołam mój skrypt otoki w następujący sposób:
wrapper.sh -x "blah blup"
wtedy tylko pierwszy oryginalny argument (-x) jest przekazywany do „other_tool”. W rzeczywistości nie tworzę podpowłoki, ale przekazuję oryginalne argumenty powłoce na telefonie z Androidem, co nie powinno mieć znaczenia:
#!/bin/bash
# ...
adb sh -c "other_tool -a -b $@"
Żadne z rozwiązań nie działa dobrze. Wystarczy podać x / \ \ \ "b \" / aaaaa / \ 'xxx \ rrrr \' / zz \ "offf \" jako parametr i nie powiodą się.
Oto proste opakowanie, które obsługuje każdą skrzynkę. Zwróć uwagę, jak dwukrotnie unika każdego argumentu.
źródło
Zmień
$@
na$*
. Zrobiłem mały test lokalny i działa w moim przypadku.Zapisywanie jako
test.sh
i wykonywanie go dajeJak widać, istnieje subtelna różnica między
$*
i$@
. Zobacz np. Http://ss64.com/bash/syntax-parameters.htmlAby odpowiedzieć na pytanie uzupełniające w komentarzach: musisz uciec np. „Dwa razy” spacją, aby przekazać ciąg z separatorem jako połączony argument, np. Ze
test.sh
zmodyfikowanymwc
opakowaniem:To działa:
ale:
źródło
wrapper.sh -x "blah blup"
wówczas podpowłoka otrzymuje TRZY parametry (-x, bla, blup) zamiast DWA (-x, „bla blup”)"Blah\ blup"
. Wypróbuj i sprawdź, czy to działa.Nie udaje się, ponieważ zmuszasz tablicę (parametry pozycyjne) do łańcucha.
"$@"
jest magiczny, ponieważ daje ci każdy osobny parametr jako poprawnie cytowany ciąg. Dodanie dodatkowego tekstu przerywa magię:"blah $@"
jest tylko jednym ciągiem.Może cię to przybliżyć:
Oczywiście każdy parametr zawierający pojedynczy cytat spowoduje problemy.
źródło
Ok, więcej objaśnień:
źródło
Wypróbowałem wiele różnych rozwiązań, dobrym źródłem informacji, w tym podstawowymi informacjami i alternatywami, jest na przykład BashFAQ / 096 na Wiki Grega (alias. GreyCat) . W sumie dwa następujące są najbardziej czytelne (z działających):
Od wersji Bash 4.4 (o ile mogłem powiedzieć z AKTUALNOŚCI ) możliwe jest użycie rozszerzenia parametrów w
@Q
następujący sposób:Zauważ, że używam
$*
tutaj zamiast,$@
ponieważ chcesz"other_tool -a -b ${*@Q}"
być jednym ciągiem zamiast jednego ciągu na przekazany argument.Jeśli chcesz zrobić to samo ze zmienną tablicy bash , potrzebujesz składni
${ARRAY[*]@Q}
(w cudzysłowach).Jeśli nie masz dostępnej wersji Bash 4.4 lub nowszej lub nie masz pewności, oto moje preferowane rozwiązanie:
Zauważ, że tutaj musisz użyć
"$@"
zamiast$@
lub"$*"
lub$*
ponieważ nie chcesz dzielenia słów w argumentach, więc nie można użyć wariantów bez cudzysłowu i chcesz zachować liczbę argumentów, więc"$*"
nie można użyć, jak by się przyłączyła wszystkie argumenty w jednym ciągu. Następnie funkcja zwraca wszystkie argumenty w jednym ciągu.Jeśli nie zależy ci na dodatkowej spacji przed pierwszym argumentem, możesz zmienić
printf
ciąg formatu na" %q"
i usunąćseparator
zmienną. Lub możesz użyć jednowierszowej odpowiedzi Gordona Davissona .Te rozwiązania działają ze wszystkimi przypadkami, które mógłbym wymyślić, w szczególności:
escapeBashArgs
→ nicescapeBashArgs "" ""
→'' ''
escapeBashArgs " " " "
→' ' ' '
lub\ \ \ \ \
( ostatnia przestrzeń jest zjedzona przez ten renderer stron )escapeBashArgs "a b" c\ d "arg with newline"
→'a b' 'c d' $'arg with\nnewline'
luba\ \ \ \ \ \ b c\ d $'arg with\nnewline'
( nowa linia znajduje się pomiędzywith
inewline
, w innych pozycjach wynika z zawijania linii na tej stronie )escapeBashArgs '$"'\''({:})'
→'$"'\''({:})'
lub\$\"\'\(\{:\}\)
escapeBashArgs x/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
→'x/ "b"/aaaaa/'\''xxx yyyy'\''/zz"offf"'
lubx/\ \ \"b\"/aaaaa/\'xxx\ yyyy\'/zz\"offf\"
(Testowane z wydaniem GNU bash 5.0.3 (1).)
źródło
źródło