Удалить последний аргумент из списка аргументов оболочки script (bash)
Этот вопрос касается bash script, который запускается в osx automator. Я использую действия automator, чтобы получить и отфильтровать кучу ссылок на файл от искателя. Затем я добавляю к этому списку имя родительской папки, также через действие автомата. Затем Automator передает эти аргументы в действие под названием "run shell script". Я точно не знаю, как automator вызывает script, но список аргументов выглядит так, как показано на экране: echo "[email protected]"
/Объемы/G-рейд/Онлайн/WAV_TEST/Testbok 50/01/01000 43-001.wav/Объемы/G-рейд/Онлайн/WAV_TEST/Testbok 50/02/02000 43-002.wav/Тома/G-Raid/Online/WAV_TEST/Testbok 50/03/03000 43-003.wav/Объемы/G-рейд/Онлайн/WAV_TEST/Testbok 50
В этом случае путь к 3 файлам и папке.
В оболочке script запускаю приложение с именем ripcheckc * с аргументами, переданными от автомата минус последний аргумент (папка) в списке.
Я использую это, чтобы удалить последний аргумент:
_args=( "[email protected]" )
unset _args[${#_args[@]}-1]
И это echo $_args
:
/Объемы/G-рейд/Онлайн/WAV_TEST/Testbok 50/01/01000 43-001.wav/Объемы/G-рейд/Онлайн/WAV_TEST/Testbok 50/02/02000 43-002.wav/Тома/G-Raid/Online/WAV_TEST/Testbok 50/03/03000 43-003.wav
То же, что и раньше, но без папки.
Теперь, если я запустил ripcheckc с аргументом "[email protected]"
в качестве аргумента, он работает (но позже не будет из-за этого последнего пути в списке аргументов). Если я использую ${_args[@]}
, приложение будет просто отменено молча. Когда я эхо [email protected]
и _args
, результат выглядит идентичным, за исключением последнего аргумента.
Мой вопрос: в чем разница между [email protected]и $_args, которые делают первый допустимый ввод, а второй не?
* Приложение ripcheckc
Надеюсь, мой вопрос имеет смысл.
EDIT: разрешено.
Ответы
Ответ 1
Предполагая, что у вас уже есть array
, вы можете сказать:
unset "array[${#array[@]}-1]"
Например, если ваш скрипт содержит:
array=( "[email protected]" )
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
Ответ 2
Я использовал этот однострочник bash
раньше
set -- "${@:1:$(($#-1))}"
Он устанавливает список аргументов в текущий список аргументов, за исключением последнего аргумента.
Как это устроено:
-
$#
это количество аргументов -
$((...))
является арифметическим выражением, поэтому $(($#-1))
на единицу меньше количества аргументов. -
${variable:position:count}
является выражением подстроки: оно извлекает count
символов из variable
начинающейся с позиции. В особом случае, когда variable
равна @
, что означает список аргументов, она извлекает count
аргументов из списка, начинающегося с position
. Здесь position
равна 1
для первого аргумента, а count
на единицу меньше количества аргументов, разработанных ранее. -
set -- arg1...argn
устанавливает список аргументов для заданных аргументов
Таким образом, конечный результат состоит в том, что список аргументов заменяется новым списком, где новый список является исходным списком, за исключением последнего аргумента.
Ответ 3
Вы также можете получить все, кроме последнего аргумента, с помощью
"${@:0:$#}"
что, честно говоря, немного отрывочно, поскольку, как представляется, (ab) используется тот факт, что аргументы нумеруются начиная с 1, а не 0.
Обновление: это работает только из-за ошибки (исправлено не ранее 4.1.2) при обработке [email protected]
. Он работает в версии 3.2.