Привет. Странный факт - всю неделю с нетерпением ждешь выходных, а когда дождался, щелчок пальцами и снова наступил понедельник. А когда отдыхать-то? В рабочие дни разгребаешь рабочую рутину, в выходные разгребаешь домашнюю рутину.

Вот такой вот замкнутый круг получается. С другой стороны ты всегда находишься при деле, в потоке. Меньше времени остается на нытье и на самокопание. А это уже большой плюс. Окей, поныли и хватит, летсгоу!

Ты тёртый калач и всяко знаешь про специальные переменные со знаком $. Держу пари, знаешь только про базовые и часто используемые, типа $? и $1.

Сегодня рассмотрим еще парочку $@ и $*. Эти специальные переменные по сути выполняют одну и ту же задачу: выводят список всех аргументов, переданных скрипту. Но естественно есть различия в их использовании.

Голову не грей, теория всегда душная, сейчас на примерах рассмотрим и всё у тебя в голове сложится как надо.

Переменная $@

Начнем с $@, накидываем скрипт:

echo "Изучаем \$@"
for arg in $@; do
    echo "Аргумент: $arg"
done

Запускаем так:

./script.sh 1 2 '3 with spaces'

На экран выводится:

Изучаем $@
Аргумент: 1
Аргумент: 2
Аргумент: 3
Аргумент: with
Аргумент: spaces

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

А теперь немного переделаем скрипт (добавим кавычки) и запустим с теми же аргументами:

echo "Изучаем \$@ с кавычками"
for arg in "$@"; do
    echo "Аргумент: $arg"
done

В этот раз на экран выведется такое:

Изучаем $@ с кавычками
Аргумент: 1
Аргумент: 2
Аргумент: 3 with spaces

Вот! Тут мы получили уже более ожидаемый результат. Массив: {$1, $2, $3}

Переменная $*

echo "Изучаем \$*"
for arg in $*; do
    echo "Аргументы: $arg"
done

После запуска с такими же аргументами:

Изучаем $*
Аргументы: 1
Аргументы: 2
Аргументы: 3
Аргументы: with
Аргументы: spaces

Получаем то же самое, что и с $@ без кавычек. Шило на мыло. А вот если заключить $* в кавычки:

echo "Изучаем \$*"
for arg in "$*"; do
    echo "Аргументы: $arg"
done

На экране мы получим:

Изучаем $*
Аргументы: 1 2 3 with spaces

Вот и отличие. Оно небольшое, оно практически ненужное. Но в этом и кроются детали. Все аргументы объединились в одну строку, отделённую символом пробела, заданным в IFS (пробел по умолчанию).

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Если это не знать, то легко можно наступить на грабли.

Вот пример как заменить IFS разделитель (пробел на запятую):

echo "Изучаем \$*"
IFS=","
for arg in "$*"; do
    echo "Аргументы: $arg"
done

Вывод будет таким:

Изучаем $*
Аргументы: 1,2,3 with spaces
Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Как «эффект бабочки», забыл поставить кавычки, сломал в будущем логику. Поставил кавычки, сломал другую логику. Куда ни ткни, вечно какие-то костыли.

Я конечно сомневаюсь, что ты пользуешься таким высокоуровневым программированием (я не пользуюсь), но порой бывает натыкаешься на чужие скрипты с подобной логикой. И тогда важно не попасть в просак.

А что такое просак, хорошо объясняется в фильме «Жмурки».

Ладно, не смею тебя больше отвлекать. Увидимся. Хорошего понедельника!