62

Идеальный скрипт на bash 2 | Bash ideal script 2

Сегодня продолжим изучать наш идеальный скрипт из предыдущего видео (видео прошлой части). Разберёмся с непонятными конструкциями в bash [] и [[]] и обсудим, когда можно не ставить кавычки вокруг переменных. Ниже видео с разбором, а кому удобнее текстовый вариант — добро пожаловать ниже.

Давайте разбираться. Двойные квадратные скобки в современном bash - это ключевое слово, такое же, как for. Проверить это можно с помощью команды type. Одинарные квадратные скобки - это встроенная команда, такая же, как test. Что из этого следует? Да фиг знает, по факту. Просто интересно. А вот внутри одинарных и двойных квадратных скобок можно использовать разные конструкции.

Для сравнения [[ и [ нашёл для вас очень наглядную таблицу

Источник: <!--noindex--><a href="https://pikabu.ru/story/idealnyiy_skript_na_bash_2__bash_ideal_script_2_11674891?u=https%3A%2F%2Fmywiki.wooledge.org%2FBashFAQ%2F031&t=https%3A%2F%2Fmywiki.wooledge.org%2FBashFAQ%2F031&h=7d8e895e02f84a56d75471e8cd350d73e7f6c535" title="https://mywiki.wooledge.org/BashFAQ/031" target="_blank" rel="nofollow noopener">https://mywiki.wooledge.org/BashFAQ/031</a><!--/noindex-->

Источник: https://mywiki.wooledge.org/BashFAQ/031

Например, знак меньше для одинарных скобок нужно экранировать, как и скобки. Для двойных скобок работают привычные программисту логические операции, регулярные выражения и прочие приятные штуки. Глобально, нет причин сейчас использовать одинарные квадратные скобки. Разве что ради переносимости.

Но про переносимость куда мы говорим? Действительно, двойные квадратные скобки появились не сразу. В разделе 7.1 книги Advanced Bash-Scripting Guide (версия на русском) написано, что конструкция появилась в bash версии 2.02. Кстати, это очень большая и вкусная книжка по bash, рекомендую её, если вы зачем-то решили стать в баше экспертом. Там под тысячу страниц, материал не для слабых духом. Есть и на русском, и на английском.

Так когда появились двойные скобки? Проверим changelog баша, там можно найти первое упоминание конструкции [[]] в версии 2.02. А потом можно найти релиз, и это 1998 год. 1998, Карл. Надеюсь, все обновились с тех пор.

В man bash можно найти описание [[]], лучше посмотрите в видео этот фрагмент.

Соберём на коленке пример демонстрации важности двойных кавычек.

a="hello world"

if [[ $a == "hello world" ]]

then

echo "success"

fi

# в видео показан однострочник ниже

if [[ $a == "hello world" ]]; then echo "success"; fi

И всё хорошо, внутри [[]] действительно можно не применять кавычки, bash всё сделает корректно. Но потом модифицируем пример

# так неправильно!

if [[ $a == "hello world" ]]; then echo "success"; touch $a; fi

И вот этот код уже ломается. Вместо создания одного файла "hello world" создаются два отдельных файла. Потому что в touch надо кавычками защищать переменную

# так нормально, но тяжело объяснить, где нужны кавычки

if [[ $a == "hello world" ]]; then echo "success"; touch "$a"; fi

А теперь объясните джуну, где надо ставить кавычки, а где не надо. Самое простое правило - кавычки должны быть везде. Великий и ужасный Гудвин, ой, то есть баш, очень неустойчив к разного рода ошибкам. По опыту жить проще с ядрёным стайл-гайдом, по которому чисто визуально можно выявить ошибку. Есть переменная? Должны быть кавычки.

# так безопаснее всего

if [[ "$a" == "hello world" ]]; then echo "success"; touch "$a"; fi

Давайте попробуем сконструировать выражение для оценки времени выполнения. Как корретно измерять время выполнения я планирую снять отдельное видео. Пока не будем вдаваться в детали и попробуем собрать нужную конструкцию

Утилита time выдаёт временные характеристики работы программы. Сейчас нас интересует блок real, где указано общее время работы программы согласно системному таймеру, то есть время от запуска команды до её завершения

time echo $( i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i )

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

Вернёмся к замене -lt на треугольный знак меньше. Попробуем

# ОШИБОЧНОЕ 2 итерации вместо 1кк

time echo $( i=0; while [[ $i < 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i )

Вау! Отработало мгновенно. Но неправильно. Обратите внимание на вывод - прошло только 2 итерации. Потому что два больше миллиона, если смотреть на них как на строки. Строковое сравнение идёт посимвольно, и два больше 1 - истина, дальше смотреть не требуется.

По факту, нужно использовать арифметическое выполнение

time echo $( i=0; while (( $i < 1000000 )); do i=$(( $i+1 )) ; done; echo $i )

А теперь ещё раз. Как вы думаете, в большом скрипте легко обнаружить такую ошибку? Это отладочный ад. Поэтому используйте -lt и аналогичные конструкции в баше, чтобы сэкономить себе время

Подытожим: всегда используйте двойные квадратные скобки в if и while, всегда защищайте ваши переменные двойными кавычками, даже если в отдельных конструкциях баш делает это за вас. Пишите поддерживаемый код, и да пребудет с вами баш.

Заходите в наш канал DevFm в телеграмм, где выходят годные материалы для middle плюс python разработчика. Если хотите разобраться с азами Linux, то добро пожаловать в наш бесплатный курс cli-for-dev на степике. Буду рад, если вы поддержите нас позитивными оценками и обратной связью по курсу.

Больше постов читайте по тегу «Программирование». А если хотите изучить новую профессию, посмотрите актуальные курсы от проверенных школ с реальными отзывами на сайте Пикабу Курсы.

GNU/Linux

1.2K постов15.6K подписчиков

Правила сообщества

Все дистрибутивы хороши.

Будьте людьми.

3
Автор поста оценил этот комментарий

time echo $( i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i )

А когда дело еще касается awk или sed, то вообще хтонический ужас душу холодит.

раскрыть ветку (1)
3
Автор поста оценил этот комментарий

О да. За то их и любим. Безысходность и хтонический ужас

1
Автор поста оценил этот комментарий
Поправьте тут или я ещё не проснулся или тут одно и тоже.
В целом было интересно, спасибо за статью!
Иллюстрация к комментарию
раскрыть ветку (1)
2
Автор поста оценил этот комментарий

Дело в кавычках. В первом случае touch $a (нет кавычек, переменная с пробелом внутри развалится на два разных аргумента), во втором touch "$a" (переменная с пробелом останется одним аргументом с пробелом внутри)

Для примера с a="hello world" первая команда без кавычек создаст два файла, вторая команда с кавычками – один файл с пробелом внутри

показать ответы
3
DELETED
Автор поста оценил этот комментарий

Консольные однострочники в баше хороши, да. Я к PowerShell так и не смог привыкнуть вот это вот Get-NetIPAddress -Force -Table -Interface | Select-String -Name "Беспроводное соединение 2"

Но вот в скриптах, увольте. Понятно что легаси, понятно что не просто так все это появилось, понятно что можно решить любую проблему, но... скобочки такие, скобочки сякие, скобочки двойные, двойные разные, кавычки такие, кавчки другие, местами брейнфак(https://ru.wikipedia.org/wiki/Brainfuck) как-то.

раскрыть ветку (1)
2
Автор поста оценил этот комментарий

По факту, правила достаточно просты и запоминаются через месяц практики – как и с любым другим языком программирования. Некоторые конструкции, конечно, ужасны. Из-за этого без практики язык быстро забывается. Из-за распространенности и стабильности баш для администрирования не имеет альтернатив. А для автоматизации мелких задач он просто хорош. По части автоматизации баш легко заменяет питон, как куда более простой и современный инструмент. Но питон довольно быстро эволюционирует, что для автоматизации не очень удобно :)


В общем, баш лучше знать, чем не знать. Но инструмент надо выбирать под задачу. Я как-то увлёкся и одну систему на базе написал

.. там было 2к строк кода. Всё проклял в процессе отладки, несмотря на хорошую архитектуру и наличие десятка небольших модулей. Всё равно был адy, никому не рекомендую

показать ответы
1
Автор поста оценил этот комментарий

ненавижу bash. До использования кавычек и двойных скобок дошёл сам, потому что заипался.)) ABS - книга для упоротых, конечно))) За пост спасибо)

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Люди делятся на два типа – кто ещё ненавидит bash и кто уже ненавидит bash ;)

1
Автор поста оценил этот комментарий

Идеальный скрипт на баш - не на баш

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

Скорее, идеальный скрипт должен быть не на баш – тут да, есть такое мнение. Но распространенность bash сделала его своеобразной латынью разработчиков. Можно сделать довольно много лёгким росчерком пера, без необходимости тащить кучу библиотек – ОС уже всё предоставляет

1
Автор поста оценил этот комментарий

а можно ссылку на первую часть?

раскрыть ветку (1)
2
DELETED
Автор поста оценил этот комментарий

а меня bash вгоняет в уныние, особенно после всяких питонов и прочих powershell.

Да понятно, когда баш писался то на экране было 25 строк и 80 символов и использование конструкций вида:

time echo $( i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i )

оправдано. Но в 2024 смотреть на это больно, как будто на обфускацированный JS код читаешь. За отступы вроде денег не берут, но каждый второй скрипт - паровоз(или мне так везет?). А еще очень прикалывает: присвоение переменной VAR=... а считывание $VAR, почему-у-у-у? Почему не $VAR=?

*да я знаю что работа идет с переменными окружения

раскрыть ветку (1)
1
Автор поста оценил этот комментарий

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


Собственно, в предыдущем видео я всё аккуратно в скрипте делал, без ужасающих однострочников. В проде за однострочники надо бить по рукам. Собственно, как в питоне за лямбды, выходящие за пределы чего-то тривиального.


Хотя, блин, писать однострочники весело :)

показать ответы
0
Автор поста оценил этот комментарий

с помощью strace, например

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

и так покрутил, и сяк. У меня strace показывает схожий вывод для [ и [[, и лишние форки для [ я найти не смог

2
Автор поста оценил этот комментарий

Тайна сия велика есть. /usr/bin/[ - это бинарник ;) Такое вот легаси.


Как и все эти bin и usr/bin. У чуваков просто места не диске не было, поэтому раскидали по разным путям. А потом это уже обросло смыслами. По типу: "что имел в виду художник/писатель в своем произведении". А он ничего не имел, у него просто места не было 50 лет назад ;)

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

О да, деление по каталогам - адище. Ещё /usr/local/bin и прочее безобразие. А потом поверх этого ещё и толстые snap пакеты. С этой точки зрения порядка вообще нет

1
Автор поста оценил этот комментарий

"[" запускает процесс (fork + exec), "[[" -- нет. поэтому такая разница во времени выполнения.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

А как проверить этот тезис? Или где такое написано?

показать ответы
0
Автор поста оценил этот комментарий

Отступы в баше имеют значение :(

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

В каком смысле? Интерпретатору на отступы пополам. Читателю, понятное дело, отступы важны, как и везде

показать ответы
1
Автор поста оценил этот комментарий
Прошу прощения не заметил!
Да bash иногда очень сильно удивляет.
раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Вот поэтому я и сформулировал правило "всегда переменные брать в кавычки") Визуально очень легко пропустить, а потом баг хрен найдёшь

1
Автор поста оценил этот комментарий

после слов "вкусная книжка" читать перестал. аффтар недотёпа.

раскрыть ветку (1)
Автор поста оценил этот комментарий

А что не так?

1
Автор поста оценил этот комментарий

в смысле "a=b" и "a = b" в баше - это сильно разное :\


или какие отступы?

раскрыть ветку (1)
Автор поста оценил этот комментарий

А, речь про пробелы. Да, с ними в баше тяжело

Отступы – это когда в начале строки, что показывает вложенность конструкций, я думал о них речь

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества