В чем разница между $@ и $*

В чем разница между $@ и $*

В соответствии сэта страница, $@ и $* делают практически одно и то же:

The $@ holds list of all arguments passed to the script. 
The $* holds list of all arguments passed to the script.

Просматривая все самые популярные результаты в Google, я не смог найти объяснения, почему существуют два, казалось бы, дублирующих друг друга синтаксиса.

Похоже, в моих сценариях они работают одинаково.

cat foo.sh
#!/bin/bash
echo The parameters passed in are $@
echo The parameters passed in are $*

./foo.sh herp derp
The parameters passed in are herp derp
The parameters passed in are herp derp
  1. Является ли один вариант более предпочтительным, чем другой?
  2. Почему существуют две встроенные переменные, выполняющие одну и ту же функцию?

Дополнительные источники
bash.cyberciti.biz

решение1

Они не одинаковы. $*— это одна строка, тогда как $@— это фактический массив. Чтобы увидеть разницу, выполните следующий скрипт следующим образом:

 > ./test.sh one two "three four"

Сценарий:

#!/bin/bash

echo "Using \"\$*\":"
for a in "$*"; do
    echo $a;
done

echo -e "\nUsing \$*:"
for a in $*; do
    echo $a;
done

echo -e "\nUsing \"\$@\":"
for a in "$@"; do
    echo $a;
done

echo -e "\nUsing \$@:"
for a in $@; do
    echo $a;
done              

Объяснение и результаты для четырех случаев приведены ниже.

В первом случае параметры рассматриваются как одно длинноецитируетсянить:

Using "$*":
one two three four

Случай 2 (без кавычек) — строка разбивается на слова с помощью forцикла:

Using $*:
one
two
three
four

Случай 3 — каждый элемент $@ рассматривается как строка в кавычках:

Using "$@":
one
two
three four

Последний случай — он обрабатывает каждый элемент как строку без кавычек, поэтому последний элемент снова делится на for three four:

Using $@:
one
two
three
four

решение2

Разница заключается в том, как они расширяются.

$*расширяется до одного аргумента, все элементы которого разделены пробелами (на самом деле это первый символ $IFS).
$@расширяется до нескольких аргументов.

Например

#!/bin/bash
echo "With *:"
for arg in "$*"; do echo "<$arg>"; done
echo
echo "With @:"
for arg in "$@"; do echo "<$arg>"; done

 

$ /tmp/test.sh 1  2 "3  4"
With *:
<1 2 3  4>

With @:
<1>
<2>
<3  4>

решение3

Вы можете просмотретьРуководство для начинающих по Bashдля получения дополнительной информации. Они делают практически то же самое, с разницей в том, как это разделено:

$*- Расширяется до позиционных параметров, начиная с единицы. Когда расширение происходит в двойных кавычках, оно расширяется до одного слова со значением каждого параметра, разделенного первым символом специальной переменной IFS.

$@- Расширяется до позиционных параметров, начиная с единицы. Когда расширение происходит в двойных кавычках, каждый параметр расширяется до отдельного слова.

Но если вы не установите IFSзначение, отличное от значения по умолчанию, оно может выглядеть идентично.

решение4

Является ли один вариант более предпочтительным, чем другой?

Короткий ответ: "$@".

Если вы используете их без двойных кавычек, они одинаковы. В этом случае нет предпочтений относительно одного. Но я предлагаю вам всегда использовать их с двойными кавычками, если только вы не знаете, что именно вы хотите.

Почему существуют две встроенные переменные, выполняющие одну и ту же функцию?

$*Между и нет разницы $@, но "$@"и "$*"имеют.

Вы можете увидеть мой ответ вэта почтачтобы увидеть, чем они отличаются.

Связанный контент