Доступ к аргументам командной строки bash $@ vs $*
Во многих SO-вопросах и руководствах по bash я вижу, что могу получить доступ к аргументам командной строки в сценариях bash двумя способами:
$ ~ >cat testargs.sh
#!/bin/bash
echo "you passed me" $*
echo "you passed me" $@
Что приводит к:
$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2
В чем разница между $*
а также $@
?
Когда следует использовать первое и когда следует использовать второе?
4 ответа
Разница появляется, когда указаны специальные параметры. Позвольте мне проиллюстрировать различия:
$ set -- "arg 1" "arg 2" "arg 3"
$ for word in $*; do echo "$word"; done
arg
1
arg
2
arg
3
$ for word in $@; do echo "$word"; done
arg
1
arg
2
arg
3
$ for word in "$*"; do echo "$word"; done
arg 1 arg 2 arg 3
$ for word in "$@"; do echo "$word"; done
arg 1
arg 2
arg 3
Еще один пример важности цитирования: обратите внимание, что между "arg" и числом есть 2 пробела, но если я не смогу процитировать $word:
$ for word in "$@"; do echo $word; done
arg 1
arg 2
arg 3
и в баш, "$@"
список по умолчанию для перебора:
$ for word; do echo "$word"; done
arg 1
arg 2
arg 3
Хорошая удобная обзорная таблица из Bash Hackers Wiki:
где c
в третьем ряду находится первый символ $IFS
, внутренний разделитель полей; переменная окружения.
Если аргументы должны быть сохранены в переменной скрипта, и предполагается, что аргументы будут содержать пробелы, я искренне рекомендую использовать "$*"
трюк с внутренним разделителем полей $IFS
установить на вкладку.
$*
Расширяется до позиционных параметров, начиная с единицы. Когда раскрытие происходит в двойных кавычках, оно расширяется до одного слова со значением каждого параметра, разделенного первым символом специальной переменной IFS. То есть "$*" эквивалентно "$1c$2c...", где c - первый символ значения переменной IFS. Если IFS не установлен, параметры разделяются пробелами. Если IFS равен нулю, параметры объединяются без промежуточных разделителей.
$@
Расширяется до позиционных параметров, начиная с единицы. Когда раскрытие происходит в двойных кавычках, каждый параметр раскрывается в отдельное слово. То есть "$@" эквивалентно "$1" "$2" ... Если раскрытие в двойных кавычках происходит внутри слова, расширение первого параметра объединяется с начальной частью исходного слова и расширением последнего параметра объединяется с последней частью исходного слова. Когда нет позиционных параметров, "$@" и $@ расширяются до нуля (то есть они удаляются).
Источник: Баш человек
$@ совпадает с $*, но каждый параметр является строкой в кавычках, то есть параметры передаются без изменений, без интерпретации или расширения. Это означает, среди прочего, что каждый параметр в списке аргументов рассматривается как отдельное слово.
Конечно, "$@" следует заключать в кавычки.
Этот пример let может выделить разницу между "at" и "asterix", когда мы их используем. Я объявил два массива "фрукты" и "овощи"
fruits=(apple pear plumm peach melon)
vegetables=(carrot tomato cucumber potatoe onion)
printf "Fruits:\t%s\n" "${fruits[*]}"
printf "Fruits:\t%s\n" "${fruits[@]}"
echo + --------------------------------------------- +
printf "Vegetables:\t%s\n" "${vegetables[*]}"
printf "Vegetables:\t%s\n" "${vegetables[@]}"
Смотрите следующий результат в коде выше:
Fruits: apple pear plumm peach melon
Fruits: apple
Fruits: pear
Fruits: plumm
Fruits: peach
Fruits: melon
+ --------------------------------------------- +
Vegetables: carrot tomato cucumber potatoe onion
Vegetables: carrot
Vegetables: tomato
Vegetables: cucumber
Vegetables: potatoe
Vegetables: onion