Разница между $ @ и $ *

Я написал простой скрипт, который принимает любое количество параметров, чтобы продемонстрировать разницу между $@ и $*:

#!/bin/bash                                                                
echo "double quoted $*     $@"
echo 'single quoted $*     $@'

На CLI я сделал

$./stuff.sh a b c d e f dfs 

И вот что распечатывает

double quoted a b c d e f dfs     a b c d e f dfs
single quoted $*     $@

Поскольку они идентичны, означает ли это, что $@ равно $*? Или я что-то упускаю?


person cyc115    schedule 27.09.2013    source источник
comment
См. this, this, this, это.   -  person devnull    schedule 27.09.2013


Ответы (3)


Из специальных параметров в справочном руководстве Bash

*

Расширяется до позиционных параметров, начиная с единицы. Когда раскрытие происходит в двойных кавычках, оно расширяется до одного слова со значением каждого параметра, разделенным первым символом специальной переменной IFS. То есть «$ *» эквивалентно «$ 1c $ 2c…», где c - это первый символ значения переменной IFS. Если IFS не задан, параметры разделяются пробелами. Если IFS имеет значение NULL, параметры объединяются без промежуточных разделителей.

@

Расширяется до позиционных параметров, начиная с единицы. Когда раскрытие происходит в двойных кавычках, каждый параметр заменяется отдельным словом. То есть «$ @» эквивалентно «$ 1», «$ 2»…. Если расширение в двойных кавычках встречается внутри слова, расширение первого параметра объединяется с начальной частью исходного слова, а расширение последнего параметра объединяется с последней частью исходного слова. Когда нет позиционных параметров, «$ @» и $ @ заменяются на ничего (т. Е. Удаляются).

Лучше на примере:

$ d=(a b c)
$ for i in "${d[*]}"; do echo $i; done <---- it is a field all together
a b c
$ for i in "${d[@]}"; do echo $i; done <---- each item is a different field
a
b
c
person fedorqui 'SO stop harming'    schedule 27.09.2013
comment
Правильная информация, но со ссылкой на действительно ужасный источник. (Одно из постоянных раздражений в #bash - это помощь людям отучать ошибки, которым их научила писать ABS). - person Charles Duffy; 27.09.2013
comment
Точно я просто искал ссылку получше. Обновлено :) - person fedorqui 'SO stop harming'; 27.09.2013

$ set -- "hello world" foo bar
$ printf '<%s> ' "$@"; echo
<hello world> <foo> <bar>     # "$@" keeps original separation
$ printf '<%s> ' "$*"; echo
<hello world foo bar>         # "$*" combines everything into one string
$ printf '<%s> ' $*; echo
<hello> <world> <foo> <bar>   # $* (no quotes) loses delimitation entirely.
$ printf '<%s> ' $@; echo
<hello> <world> <foo> <bar>   # unquoted, $@ is identical to unquoted $*.

Технически $* не ограничивается разделением пробелами; он использует первый символ $IFS. Это может быть использовано в ваших интересах:

jars=( *.jar )
IFS=:
export CLASSPATH=${jars[*]}
person Charles Duffy    schedule 27.09.2013
comment
Не могли бы вы привести пример для $@ (без двойных кавычек), как вы это сделали для других? Ваши примеры помогают мне быстро понять различия. - person Elie G.; 08.01.2020
comment
При использовании без кавычек $@ в точности совпадает с $* без кавычек. Я с удовольствием добавлю пример на этот счет. - person Charles Duffy; 08.01.2020

Из http://linuxsig.org/files/bash_scripting.html:

$ * Сохраняет все аргументы, которые были введены в командной строке

so

$1 $2 ...

"$ @" Сохраняет все аргументы, введенные в командной строке, в индивидуальной кавычке.

so

"$1" "$2" ...
person Alberto Zaccagni    schedule 27.09.2013
comment
$1 $2 ... истинно только со значением по умолчанию IFS. Если вы установите IFS=:, то он станет $1:$2:... f / e. - person Charles Duffy; 08.01.2020