Доступ к аргументам командной строки 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" ... Если раскрытие в двойных кавычках происходит внутри слова, расширение первого параметра объединяется с начальной частью исходного слова и расширением последнего параметра объединяется с последней частью исходного слова. Когда нет позиционных параметров, "$@" и $@ расширяются до нуля (то есть они удаляются).

Источник: Баш человек

$@ совпадает с $*, но каждый параметр является строкой в ​​кавычках, то есть параметры передаются без изменений, без интерпретации или расширения. Это означает, среди прочего, что каждый параметр в списке аргументов рассматривается как отдельное слово.

Конечно, "$@" следует заключать в кавычки.

http://tldp.org/LDP/abs/html/internalvariables.html

Этот пример 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
Другие вопросы по тегам