Вопрос или проблема
Я хочу:
- получить все параметры команды, кроме первых двух
- создать строку с результатом предыдущего шага
Итак, если у меня есть эта команда:
mycommand param1 param2 param3 param4 param5 paramN
Я должен получить эту строку:
"param3 param4 param5 paramN"
Я знаю, что чтобы получить все параметры, кроме первых двух, я могу:
echo "'${@:3}'"
А чтобы поместить все параметры в строку, я могу:
echo "'$*'"
Но я не знаю, как объединить эти два подхода, чтобы достичь того, что я хочу.
В bash, как и в ksh93, откуда bash заимствовал эту синтаксическую конструкцию, просто используйте "${*:3}"
(не убирайте кавычки), предварительно установив $IFS
на желаемый символ разделителя:
mycommand() {
local IFS=' ' # первый символ $IFS используется для объединения "$*"
printf 'Третий с конца, объединенный пробелами: "%s"\n' "${*:3}"
}
bash-5.2$ mycommand param1 param2 param3 param4 param5 paramN
Третий с конца, объединенный пробелами: "param3 param4 param5 paramN"
Это также будет работать в последних версиях zsh
, но там лучше использовать ${(j[ ])@[3,-1]}
, где вы можете явно указать, как элементы должны быть объединены, не изменяя глобальный параметр, и используя синтаксис $array[first,last]
, а не ${array[*]:offset:length}
из ksh93, который конфликтует с модификаторами csh и Bourne’s ${var:-value}
(но в итоге zsh поддержал это с ограничениями несколько десятилетий спустя для совместимости с ksh93/bash).
Это можно сделать с помощью команды shift
:
# cat a.sh
shift 2; echo "$*"
или
shift; shift; echo "$*"
Второй вариант дает ожидаемый результат, когда количество параметров меньше 2 (на моей bash
v4.4.12)
# ./a.sh 1 2 3 4 5 6
3 4 5 6
Чтобы поместить их в переменную:
shift 2; a="$*"
или
shift; shift; a="$*"
(смотрите выше)
Ответ или решение
В Bash вы можете легко извлечь параметры из команды, пропустив первые два и сформировав строку из оставшихся. Рассмотрим, как это можно сделать с использованием различных методов.
Способ 1: Использование переменной IFS
Можно использовать переменную IFS
для установки символа-разделителя и извлечения параметров с помощью printf
. Вот пример функции, которая выполняет эту задачу:
mycommand() {
local IFS=' ' # Установим пробел как разделитель
printf 'Третий и последующие параметры, объединенные пробелами: "%s"\n' "${*:3}"
}
Пример использования:
mycommand param1 param2 param3 param4 param5 paramN
Результат:
Третий и последующие параметры, объединенные пробелами: "param3 param4 param5 paramN"
Способ 2: Использование команды shift
Еще один способ – использовать команду shift
, чтобы "сдвинуть" параметры и затем вывести оставшиеся:
shift 2 # Сдвигаем параметры, отбрасывая первые два
echo "$*" # Выводим оставшиеся параметры
Пример использования:
mycommand() {
shift 2 # Убираем первые два параметра
a="$*" # Сохраняем оставшиеся параметры в переменной a
echo "$a"
}
mycommand param1 param2 param3 param4 param5 paramN
Результат:
param3 param4 param5 paramN
Также можно использовать «двойной сдвиг» в случае, если вы не уверены о количестве параметров, передаваемых в сценарий:
shift; shift # Сдвиг двух параметров
echo "$*"
В этом случае, если передано менее двух параметров, Bash не выдаст ошибку и просто вернет пустую строку.
Примечание
В зависимости от версии Bash и других настроек, может быть целесообразно обрабатывать случаи, когда передано недостаточно параметров, чтобы избежать неожиданных результатов.
Эти методы позволяют вам легко получить нужные параметры и объединить их в строку, подходящую для дальнейшего использования в вашем сценарии.