DanLevy.net

Тест: Bash и Shell mastery

Вы умеете разговаривать с компьютерами? Ну, вроде бы?

Проверьте свои навыки Bash‑скриптинга с этими 16 вопросами!

Охватывая переменные, циклы, условные конструкции, работу со строками, функции и от простых до хитрых подводных камней синтаксиса.

Отточите (или докажите) свои навыки shell‑скриптинга навыки!

Как объявляются переменные в Bash?

В Bash переменные объявляются без пробелов вокруг знака =. Например:

Terminal window
name=Alice

Это присваивает значение "Alice" переменной name.

Примечание: $name используется для ссылки или чтения значения переменной.

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

Кроме того, Bash чувствителен к регистру, поэтому name, NAME и Name — разные переменные.

Наконец, в именах переменных нельзя использовать пробелы или дефисы (-). Используйте подчёркивания (_) или camelCase вместо этого.

Что выведет It's 🔨 Time!?

Знаю. Сумасшедше, как быстро экранирование делает строки трудными для разбора. Представьте, как экранировать другие языки в Bash‑строках — со всеми этими кавычками, апострофами и символами $, которые могут вас сломать. 🫠

Single quotes need escaping inside single-quoted strings. The close-quote, escaped-quote, reopen-quote sequence ('\'') allows output of:

It's 🔨 Time!

Есть и другие способы решить эту задачу, но это самый распространённый.

Что выведет эта команда?

Terminal window
echo c{a,b}t

Расширение фигурных скобок {} генерирует несколько вариантов строки, по одному (или более) для каждого значения, разделённого запятыми, или шаблона.

Здесь c{a,b}t разворачивается в:

cat cbt

Итак, что будет выведено?

Terminal window
price="$100"
echo "Cost: $price"

Нумерованные переменные имеют особое значение. В данном случае $1 — это специальная переменная, содержащая первый аргумент, переданный скрипту или функции.

Поскольку мы запускаем скрипт в REPL, аргументов нет, поэтому $1 пустая. Оставшийся текст 00 выводится как есть.

Чтобы вывести буквальный символ $, используйте одинарные кавычки или экранируйте его обратным слешем (\\):

Terminal window
price="\$100"
echo "Cost: $price"

Что здесь происходит?

Terminal window
str="Bark bark"
echo ${str/bark/meow}

Синтаксис ${var/pattern/replacement} заменяет первое вхождение pattern на replacement. Здесь вывод:

Bark meow

Он чувствителен к регистру. Чтобы обработать как bark, так и Bark, используйте шаблон вроде ${var/[Bb]ark/Bark} или нормализуйте строку перед заменой.

Чтобы заменить все вхождения, используйте ${var//pattern/replacement}.

Чтобы заменить с начала строки, используйте ${var/#pattern/replacement}.

Чтобы заменить с конца строки, используйте ${var/%pattern/replacement}.

Как получить длину переменной в Bash?

Синтаксис ${#username} возвращает длину username.

Например:

Terminal window
username="@justsml"
echo ${#username} # => 8

Хотя wc сработает, технически это не часть Bash.

Утилита wc — старый внутренний шутливый термин, означающий “water closet”, то есть туалет. ШУТКА! Кто‑нибудь это читает?

На самом деле wc — древняя команда из POSIX (и эпохи AT&T Unix). Она сокращённо означает “word count” и может подсчитывать строки, слова и символы в файле или потоке ввода.

Что выведет этот скрипт, если файл cats.txt СУЩЕСТВУЕТ?

Terminal window
if [ -e cats.txt]; then
echo "File exists"
else
echo "File does not exist"
fi

Вы заметили отсутствующий пробел перед закрывающей скобкой?

Bash здесь довольно чувствителен: внутри скобочных выражений требуются пробелы.

Из‑за отсутствующего пробела команда [ не видит закрывающую ], Bash выводит диагностическое сообщение, считает проверку неуспешной и переходит к ветке else.

Правильный синтаксис:

Terminal window
if [ -e example.txt ]; then
echo "File exists"
else
echo "File does not exist"
fi

Примечание: двойные квадратные скобки [[ ]] рекомендованы для условных выражений. См. BashFAQ.

Как сравнивать строки в Bash?

Terminal window
cat1="Rosie"
cat2="Sunflower"
if [ "$cat1" === "$cat2" ]; then
echo "Same cat"
else
echo "Different cats"
fi

Еще одна тестовая синтаксическая ошибка!

Вы заметили недопустимый оператор ===?

Возможно, вы думали о JavaScript…

С [ ... ] Bash выводит диагностическое сообщение, и условие считается ложным, поэтому ветка else выводит Different cats. В Bash используйте = или == для сравнения на равенство.

Что выведет этот скрипт?

Terminal window
function greet () {
echo "$1"
}
greet Hi Dan

Функции в Bash могут принимать аргументы. Переменная $1 содержит первый аргумент, переданный функции.

Помните, $0 — имя скрипта, $1 — первый аргумент, $2 — второй и так далее. Пробелы разделяют аргументы. Поэтому greet Hi Dan передаёт "Hi" как первый аргумент. Чтобы передать "Hi Dan" как один аргумент, нужно заключить его в кавычки: greet "Hi Dan".

Какой оператор соединяет output одной команды со input следующей команды?

Оператор | соединяет вывод одной команды со вводом другой. Например:

Terminal window
echo "Mr. Levy 👨🏻‍🔬" | wc -m
# => 14

Как работает математика в Bash?

Синтаксис (( )) выполняет целочисленную арифметику в Bash.

Его можно использовать для простых вычислений:

Terminal window
((result = 2 + 2))
echo $result # => 4

Или для условных выражений:

Terminal window
if (( 2 > 1 )); then
echo "2 is greater than 1"
fi

Для арифметики с плавающей точкой рассмотрите использование bc или awk.

Какой из вариантов правильно умножает 10 и 0.5, выводя 5?

Синтаксис (( )) выполняет ТОЛЬКО целочисленную арифметику. То есть только целые числа, без плавающей запятой!

Bash (что может удивлять) не имеет встроенной поддержки арифметики с плавающей точкой.

Наиболее распространённое решение — использовать утилиты GNU bc или awk.

Что делает : в этом скрипте?

Terminal window
rosie="Bad cat, good cat"
echo ${rosie:9}

Синтаксис ${var:offset} извлекает подстроку, начиная с offset. Здесь вывод:

good cat

Чтобы извлечь подстроку заданной длины, используйте ${var:offset:length}.

Чтобы извлечь из конца строки, используйте ${var: -offset}. (Обратите внимание на пробел перед -!)

Что НЕ ❌ является ключевым словом для циклов в Bash?

each не является ключевым словом цикла в Bash. Основные ключевые слова циклов — for, while и until.

Хотя do технически не считается ключевым словом цикла, оно является важной частью синтаксиса цикла.

Какой вариант выполнит команду ls -l и вернёт её вывод?

Синтаксис $(ls -l) выполняет команду внутри скобок и подставляет её вывод. Например:

Terminal window
echo "Today is $(date +%F)"
# => Today is 2029-12-31

Первый вариант использует одинарные кавычки ', а не обратные кавычки. Это подавляет расширение, поэтому '$(date +%F)' просто выведет буквальную строку $(date +%F).

Хотя обратные кавычки (`ls -l`) всё ещё поддерживаются для выполнения команд, в последнее время их считают антипаттерном (в некоторых контекстах). Большинство советует использовать $(command) для лучшей читаемости и совместимости с разными оболочками и версиями.

Фигурные скобки ${} применяются для расширения переменных, а не для подстановки команд.

Символ % не используется для подстановки команд.

Какой оператор используется для объединения вывода ошибок со стандартным выводом?

Оператор 2>&1 перенаправляет стандартный поток ошибок (дескриптор файла 2) в стандартный вывод (дескриптор файла 1). Это полезно для захвата сообщений об ошибках в том же потоке вывода, что и обычный вывод.

Оставил ли мой Bash‑квиз вас в полном разруше‑нном состоянии?

Дайте знать в комментариях ниже!

Дополнительные материалы

Подтяните свои навыки Bash с помощью следующих ресурсов: