Удалить последний аргумент из списка аргументов сценария оболочки (bash)
этот вопрос касается сценария bash, который запускается в automator osx. Я использую действия automator, чтобы получить и отфильтровать кучу ссылок на файлы из finder. Затем я добавляю к этому списку имя родительской папки, также через действие automator. Затем Automator передает эти аргументы в действие под названием "запустить сценарий оболочки". Я не уверен точно, как automator вызывает скрипт, но список аргументов выглядит так, когда эхо:echo "$@"
/ Тома / G-Raid / Online/WAV_TEST / Testbok 50/01/01000 43-001.wav / Тома / G-Raid / онлайн/WAV_TEST / Testbok 50/02/02000 43-002.wav / Тома / G-Raid / онлайн/WAV_TEST / Testbok 50/03/03000 43-003.wav / Тома / G-Raid / онлайн/WAV_TEST / Testbok 50
в этом случае путь к 3 файлы и папки.
в скрипте оболочки я запускаю приложение под названием ripcheckc* с args, переданными из automator минус последний аргумент (папка) в списке.
Я использую это для удаления последнего аргумента:
_args=( "$@" )
unset _args[${#_args[@]}-1]
и echo $_args
:
/ Тома / G-Raid / Online/WAV_TEST / Testbok 50/01/01000 43-001.wav / Тома / G-Raid / онлайн/WAV_TEST / Testbok 50/02/02000 43-002.wav / Тома / G-Raid / онлайн/WAV_TEST / Testbok 50/03/03000 43-003.WAV и
то же, что и раньше, но без папки.
теперь, если я запускаю ripcheckc с "$@"
в качестве аргумента он работает (но не работает позже из-за этого последнего пути в список аргументов), если я использую ${_args[@]}
приложение будет просто молча прекратить. Когда я Эхо $@
и _args
выходные данные выглядят одинаково, за исключением последнего аргумента.
мой вопрос: в чем разница между $@ и $_args, которые делают первый допустимый вход, а второй нет?
*приложение ripcheckc
надеюсь, мой вопрос имеет смысл.
EDIT: решено.
3 ответов
при условии, что у вас уже есть array
, вы можете сказать:
unset "array[${#array[@]}-1]"
например, если ваш скрипт содержит:
array=( "$@" )
unset "array[${#array[@]}-1]" # Removes last element -- also see: help unset
for i in "${array[@]}"; do
echo "$i"
done
вызывая его, говоря:bash scriptname foo bar baz
вернутся:
foo
bar
я использовал этот bash
одну строчку перед
set -- "${@:1:$(($#-1))}"
он устанавливает список аргументов в текущий список аргументов, за вычетом последнего аргумента.
как работает:
-
$#
количество аргументов -
$((...))
является арифметическим выражением, поэтому$(($#-1))
на один меньше, чем количество аргументов. -
${variable:position:count}
это подстроку выражения: это экстрактыcount
символы отvariable
начиная в позиции. В особый случай здесьvariable
is@
, что означает список аргументов, он извлекаетcount
аргументы из списка, начинающегося наposition
. Вот,position
is1
для первого аргумента иcount
на один меньше, чем количество аргументов, разработанных ранее. -
set -- arg1...argn
задает список аргументов к приведенным аргументам
таким образом, конечный результат заключается в том, что список аргументов заменяется новым списком, где новый список является исходным списком, за исключением последнего аргумента.
вы также можете получить все, кроме последнего аргумента с
"${@:0:$#}"
что, честно говоря, немного отрывочно, так как кажется (ab), используя тот факт, что аргументы нумеруются, начиная с 1, а не 0.
Update: это работает только из-за ошибки (Исправлена в 4.1.2 не позднее) в обработке $@
. Он работает в версии 3.2.