Удалить последний аргумент из списка аргументов сценария оболочки (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 is 1 для первого аргумента и count на один меньше, чем количество аргументов, разработанных ранее.
  • set -- arg1...argn задает список аргументов к приведенным аргументам

таким образом, конечный результат заключается в том, что список аргументов заменяется новым списком, где новый список является исходным списком, за исключением последнего аргумента.


вы также можете получить все, кроме последнего аргумента с

"${@:0:$#}"

что, честно говоря, немного отрывочно, так как кажется (ab), используя тот факт, что аргументы нумеруются, начиная с 1, а не 0.

Update: это работает только из-за ошибки (Исправлена в 4.1.2 не позднее) в обработке $@. Он работает в версии 3.2.