Добавить в корзинуПозвонить
Найти в Дзене
Герман Геншин

Взрыв мозга: почему Bash издевается над массивами? Четыре секрета расширения, которые изменят ваше представление!

Вас когда-нибудь удивляло странное поведение массивов в Bash? Только взялись за Bash и уже чувствуете, что с массивами что-то не так? На простых примерах объясняю, почему результат бывает неожиданным — и как перестать наступать на одни и те же грабли. Если вы хоть раз писали Bash-скрипты, наверняка сталкивались с циклом for. Его синтаксис не слишком очевиден, и сам я немало путался, пока не разобрался с четырьмя главными правилами его работы. Разбираемся с массивами шаг за шагом — элемент за элементом. Давайте рассмотрим частую ошибку. Получаем один и тот же массив — обрабатываем его двумя способами: с кавычками ("${my_arr[@]}") и без кавычек (${my_arr[@]}): Массив вроде бы с двумя элементами, но почему ${my_arr[@]} без кавычек внезапно выдает четыре? Всё дело в разбиении на слова — именно об этом я сейчас расскажу. 24 дня – наши любимые гаджеты и тех-новинки Если вы только осваиваете Bash или просто хотите освежить основы — вот короткое напоминание. А опытные могут перейти к следующе
Оглавление

Вас когда-нибудь удивляло странное поведение массивов в Bash? Только взялись за Bash и уже чувствуете, что с массивами что-то не так? На простых примерах объясняю, почему результат бывает неожиданным — и как перестать наступать на одни и те же грабли.

Если вы хоть раз писали Bash-скрипты, наверняка сталкивались с циклом for. Его синтаксис не слишком очевиден, и сам я немало путался, пока не разобрался с четырьмя главными правилами его работы.

-2

Управлять данными в Bash-скриптах просто — если знаешь, как работают массивы

Разбираемся с массивами шаг за шагом — элемент за элементом.

Давайте рассмотрим частую ошибку. Получаем один и тот же массив — обрабатываем его двумя способами: с кавычками ("${my_arr[@]}") и без кавычек (${my_arr[@]}):

-3

Массив вроде бы с двумя элементами, но почему ${my_arr[@]} без кавычек внезапно выдает четыре? Всё дело в разбиении на слова — именно об этом я сейчас расскажу.

-4

HTG Wrapped 2025: 24 дня вместе с любимыми технологиями

24 дня – наши любимые гаджеты и тех-новинки

Экспресс-курс: как работает for-цикл в Bash

Если вы только осваиваете Bash или просто хотите освежить основы — вот короткое напоминание. А опытные могут перейти к следующей части.

Пример строки: "foo bar". Она взята в кавычки (одинарные или двойные), чтобы пробел не путал Bash. Кавычки дают понять интерпретатору: перед ним одно целое значение.

Bash считает "foo bar" одним словом, если это явно задано контекстом. Здесь «слово» — последовательность символов, которую Bash воспринимает, как один элемент. Чтобы не возникла путаница, буду различать bash-слова и обычные слова.

Вот массив: my_arr=("foo" "bar"). Он состоит из двух значений, которые можно легко перебрать по порядку.

Для этого обычно и применяют цикл for: он «пробегает» по массиву и позволяет делать с каждым элементом что угодно.

-5

«item» — это переменная цикла, или просто итератор. С каждым элементом массива эта переменная обновляется, и вы работаете с ней внутри цикла.

Есть разные способы пройтись по массиву в Bash, но описанный — самый популярный и понятный.

Есть ещё формат обращения к массиву через "${my_arr[*]}". Доберёмся до него чуть позже.

Расширяя параметры, Bash разделяет массив как ему заблагорассудится

Параметр в Bash — по сути, обычная переменная. Расширение параметра (parameter expansion) — это когда Bash подставляет вместо, скажем, $foo её реальное значение во время выполнения скрипта.

Если есть массив my_arr=("one a" "two b"), запись "${my_arr[@]}" превращает его в два отдельных значения: "one a" и "two b". Когда такой массив попадает в цикл for, каждое bash-слово ("one a" и "two b") по очереди становится значением переменной цикла.

Смотрите на примере:

-6

В первом случае (через «@») массив превращается в два отдельных значения: «one a» и «two b».

Во втором (через «*»), все элементы массива сливаются в одну строку с пробелом между ними.

Именно кавычки вокруг массива решают судьбу результата. Стоит их забыть — Bash начнёт делать что-то совсем неожиданное. Вот как это работает.

Разделение на слова: Bash разбивает даже самое целое на части

Как только добавляете кавычки — Bash ведёт себя корректно. А если их опустить?

-7

В обоих вариантах вместо двух получаем аж четыре значения. Почему? Без кавычек Bash сам по себе начинает делить строку на слова по пробелам, табуляциям и переводам строки. И вот "one a" распадается на «one» и «a», а "two b" — на «two» и «b».

-8

$'...' — это особое оформление строки, ANSI-C quoting: Bash превращает спецсимволы (\n, \t и т.д.) в настоящие переносы строк и табуляции. Все такие символы считаются точками разделения слов.

Хотите изменить список этих разделителей? Для этого и существует переменная окружения IFS (Internal Field Separator):

-9

Вот что чаще всего вводит в заблуждение: само «разделение на слова» — это дополнительный шаг Bash. Если посмотреть длину массива через #, она всегда равна реальному числу элементов, а не количеству получившихся слов после разбиения.

3 хитрости Bash, которые обязан знать каждый линуксоид

Раскройте для себя мощь Bash с этими простыми лайфхаками!

Всё, что вы смотрели выше, — разные способы расширения параметров (массива). Только "${my_arr[*]}" (в кавычках и со звездочкой) склеивает весь массив в одну строку, все остальные варианты превращают его в отдельные элементы. Важно: если не использовать кавычки (${my_arr[@]}), Bash обязательно дополнительно разобьёт значения на слова.

Тип

Что получится на выходе...

Будет ли Bash разбивать на слова?

"${my_arr[@]}"

Каждый элемент массива отдельно (Bash-слова)

Нет

"${my_arr[*]}"

Вся коллекция элементов склеена в одну строку

Нет

${my_arr[@]}

Каждый элемент, но Bash разбивает их на части

Да

${my_arr[*]}

Тоже элементы разбиты, как пожелает Bash

Да

Байка про слова в Bash: это непрерывная последовательность символов, вовсе не то же самое, что «слова» в человеческом смысле.

Заметили? Результаты ${my_arr[@]} и ${my_arr[*]} без кавычек одинаково дробятся Bash на кусочки.

Подпишитесь на рассылку — и массивы Bash наконец перестанут вас пугать!

Подпишитесь на рассылку — и массивы Bash наконец перестанут вас пугать!

В конце концов: чаще всего вам нужен именно "${my_arr[@]}" (в кавычках). Так Bash ведёт себя предсказуемо. Пропустите кавычки — цикл for вполне может «сломать» ваши данные. Учитывайте это правило при обработке массивов!

Те же самые принципы действуют для переменных $@ и $* — их используют при передаче аргументов функциям или скриптам.

-11

8 трюков для Linux-оболочки, которые перевернут ваше понимание Bash

Оболочка — это не только команды. Узнайте, как Bash обрабатывает ваши строки и помогает писать более чистые, безопасные скрипты!

Если вам понравилась эта статья, подпишитесь, чтобы не пропустить еще много полезных статей!

Премиум подписка - это доступ к эксклюзивным материалам, чтение канала без рекламы, возможность предлагать темы для статей и даже заказывать индивидуальные обзоры/исследования по своим запросам!Подробнее о том, какие преимущества вы получите с премиум подпиской, можно узнать здесь

Также подписывайтесь на нас в: