Napisałem skrypt, który może wygenerować dla mnie te argumenty, z cytatami
Jeśli dane wyjściowe są poprawnie cytowane dla powłoki i ufasz wynikowi , możesz eval
na nim uruchomić .
Zakładając, że masz powłokę obsługującą tablice, najlepiej byłoby użyć jej do przechowywania otrzymanych argumentów.
Jeśli ./gen_args.sh
produkuje dane wyjściowe podobne 'foo bar' '*' asdf
, możemy uruchomić, eval "args=( $(./gen_args.sh) )"
aby wypełnić tablicę wywoływaną args
wynikami. To byłoby trzy elementy foo bar
, *
, asdf
.
Możemy "${args[@]}"
jak zwykle używać do indywidualnego rozszerzania elementów tablicy:
$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
(Uwaga: cudzysłów "${array[@]}"
rozwija się do wszystkich elementów jako niezmodyfikowane odrębne argumenty. Bez cudzysłowu elementy tablicy podlegają podziałowi słów. Patrz np. Strona Tablice na BashGuide .)
Jednakże , eval
chętnie uruchamiać żadnych zastępstw powłoki, więc $HOME
na wyjściu rozwinie się do swojego katalogu domowego, a na zmianę poleceń faktycznie uruchomić polecenie w prowadzeniu płaszcza eval
. Dane wyjściowe "$(date >&2)"
utworzyłyby pojedynczy pusty element tablicy i wydrukowałyby bieżącą datę na standardowym wyjściu. Jest to problem, jeśli gen_args.sh
pobiera dane z jakiegoś niezaufanego źródła, takiego jak inny host w sieci, nazwy plików utworzone przez innych użytkowników. Dane wyjściowe mogą zawierać dowolne polecenia. (Gdyby get_args.sh
sam był złośliwy, nie musiałby niczego wysyłać, mógłby po prostu uruchomić złośliwe polecenia bezpośrednio).
Alternatywą dla cytowania powłoki, która jest trudna do przeanalizowania bez eval, byłoby użycie innego znaku jako separatora w danych wyjściowych skryptu. Musisz wybrać taki, który nie jest potrzebny w rzeczywistych argumentach.
Wybierzmy #
i wypiszmy skrypt foo bar#*#asdf
. Teraz możemy użyć niekwotowanego rozszerzenia polecenia, aby podzielić wynik polecenia na argumenty.
$ IFS='#' # split on '#' signs
$ set -f # disable globbing
$ args=( $( ./gen_args3.sh ) ) # assign the values to the array
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
Musisz IFS
cofnąć się później, jeśli zależy Ci na dzieleniu wyrazów w innym miejscu skryptu ( unset IFS
powinno działać, aby stało się domyślnym), a także użyć, set +f
jeśli chcesz użyć globowania później.
Jeśli nie używasz Bash lub innej powłoki, która ma tablice, możesz użyć do tego parametrów pozycyjnych. Wymień args=( $(...) )
się set -- $(./gen_args.sh)
i używać "$@"
zamiast "${args[@]}"
potem. (Tutaj również potrzebujesz cudzysłowów "$@"
, w przeciwnym razie parametry pozycyjne podlegają podziałowi słów).
eval
może być użyty, ale generalnie nie jest to zalecane.xargs
jest również coś do rozważenia