Невозможно использовать все аргументы $ @ с sh -c - PullRequest
2 голосов
/ 08 апреля 2019

В скрипте у меня есть команда sh -c, которая включает $@, но кажется, что учитывается только первый элемент $@:

$ set -- --no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/
$ echo "$@"
--no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/
$ sh -c "echo $@"
--no-resume-playback
$ sh -c "echo ${@[*]}"
bash: echo ${@[*]}: bad substitution

РЕДАКТИРОВАТЬ 1: Если яскопируйте массив $@ в переменную, он работает:

$ args=("$@")
$ sh -c "echo ${args[*]}"
--no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/

Как я могу использовать все аргументы $@ в вызове sh -c?

Ответы [ 2 ]

7 голосов
/ 08 апреля 2019

$@ раскрывается как отдельные слова, даже если оно заключено в двойные кавычки и выглядит как одно слово.Команда, которую вы написали, расширяется до:

sh -c "echo --no-resume-playback" https://www.facebook.com/TBN/videos/1580372468665943/

Выполнение команды: echo --no-resume-playback с $0, установленным на URL-адрес Facebook.echo --no-resume-playback не использует $0, поэтому эффективно отбрасывается.

У вас правильная идея с ${@[*]}.Как это бывает, $@ - это особый случай с уникальным синтаксисом: вам нужен $*, который расширяется до одного слова.

sh -c "echo $*"

Это немного опасно, поскольку любые аргументы с подстановочными знаками, такими как * может быть расширен.Если вы хотите быть в безопасности, вам понадобится эта более сложная версия:

sh -c 'echo "$@"' sh "$@"

. Она передает "$@" в качестве аргументов команды -c, чтобы мы могли в свою очередь использовать "$@" внутри.Обратите внимание, что я теперь переключился на одинарные кавычки: мы хотим, чтобы подоболочка расширялась "$@", а не внешняя оболочка.

И на самом деле для максимальной педантичности echo тоже не совсем безопасна.Если вы попытаетесь напечатать строку типа -n, она может быть напечатана не буквально, а вместо этого интерпретирована как опция.Самый безопасный вариант - использовать printf:

sh -c 'printf "%s\n" "$*"' sh "$@"
1 голос
/ 08 апреля 2019

Вы пробовали использовать расширение $*? Я получаю следующее:

$ sh -c "echo $*"
--no-resume-playback https://www.facebook.com/TBN/videos/1580372468665943/

Это соответствует вашим потребностям?

...