У меня есть простой скрипт, где первый аргумент зарезервирован для имени файла, а все остальные необязательные аргументы должны быть переданы в другие части скрипта.
С помощью Google я нашел эту вики , но она предоставила буквальный пример:
echo "${@: -1}"
Я не могу заставить что-нибудь еще работать, например:
echo "${@:2}"
или
echo "${@:2,1}"
Я получаю "Плохая замена" из терминала.
В чем проблема, и как я могу обработать все, кроме первого аргумента, переданного скрипту bash?
"{@:2}"
к неработоспособности, поэтому правильный ответ совпадает с приведенным выше.Ответы:
Использовать этот:
Следующий синтаксис:
будет работать, но не рекомендуется, потому что, как уже объяснил @Gordon , при использовании
*
он запускает все аргументы вместе как один аргумент с пробелами, сохраняя при@
этом разрывы между ними (даже если некоторые аргументы сами содержат пробелы ). Это не имеет значенияecho
, но это важно для многих других команд.источник
#!/usr/bin/env sh
вот почему у меня были проблемы. Ваш пример работает нормально, так же, как указано выше, после того, как я удалил этот shebang"${@:2}"
вместо этого - использование*
запускает все аргументы вместе как один аргумент с пробелами, сохраняя при@
этом разрывы между ними (даже если некоторые из аргументов сами содержат пробелы). Разница не заметна сecho
, но это имеет значение для многих других вещей.echo
прощает достаточно, чтобы соединить их для вас; другие команды могут быть не такими хорошими. Не просто используйте один или другой: изучите разницу между*
и@
, и когда использовать каждый. Вы должны использовать их примерно одинаково. Хороший пример того, когда это будет проблемой: если$3
содержит строку break (\n
), она будет заменена пробелом, если у вас есть$IFS
переменная по умолчанию .echo
используя только в качестве примера - в этом случае их не следует запускать вместе. По моему опыту, ситуации, когда вы хотите, чтобы они работали вместе, встречаются редко (см. Этот вопрос для одного примера ), и"$@"
это почти всегда то, что вы хотите. Кроме того, проблема, о которой вы упоминаете с разрывом строки, возникает, только если$@
(или$*
) не заключена в двойные кавычки.$*
довольно часто в моих сценариях.Если вы хотите решение, которое также работает в
/bin/sh
попыткеshift [n]
сдвигает позиционные параметры n раз. Ashift
устанавливает значение$1
в значение$2
, значение$2
в значение$3
и т. Д., Уменьшая значение$#
на единицу.источник
foo=shift
но не делает то, что я ожидал.foo=$(shift)
shift
(в оболочке) не имеет никакого вывода. Это просто отбрасывает$1
и сдвигает все вниз. 2)$(...)
запускает подоболочку, которая имеет свои локальные аргументы. Это сдвигает аргументы в подоболочке, что никак не влияет на родителяsomecommand "$1" "${@:2}"
делает с этим методом (то есть сдвиг "inline"), хотя?http://wiki.bash-hackers.org/scripting/posparams
Это объясняет использование
shift
(если вы хотите отбросить первые N параметров), а затем реализацию массового использованияисточник
Наткнулся на это в поисках чего то другого. Хотя пост выглядит довольно старым, простейшее решение в bash показано ниже (по крайней мере, bash 4) с использованием
set -- "${@:#}"
где # - начальный номер элемента массива, который мы хотим сохранить вперед:В основном,
set -- "${@:3}"
просто выскакивает первые два элемента в массиве, как сдвиг Perl и сохраняет все остальные элементы, включая третий. Я подозреваю, что есть способ выскочить и из последних элементов.источник