← Назад к вопросам

В чем разница между [] и [[]] в bash?

2.0 Middle🔥 251 комментариев
#Скриптинг и программирование

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между одинарными [ ] и двойными [[ ]] в Bash

В языке Bash (и других совместимых оболочках) оба оператора используются для проверки условий, но [[ ]] является более современным и мощным расширением Bash (и других оболочек типа Zsh, Ksh), в то время как [ ] — это устаревший синоним встроенной команды test, оставшийся для совместимости с POSIX. Ключевая разница в том, что [[ ]] предоставляет больше возможностей и безопаснее.

Основные отличия

1. Обработка переменных и путей

Внутри [[ ]] Bash автоматически обрабатывает переменные и не разбивает строки на слова по пробелам, что предотвращает многие ошибки.

# Пример с пробелами в переменной
file="my file.txt"
if [[ -f $file ]]; then
    echo "Файл '$file' существует."
fi
# В [[ ]] это работает корректно.

if [ -f $file ]; then
    echo "Файл '$file' существует."
fi
# В [ ] это вызовет ошибку, так как $file разобьётся на два слова: "my" и "file.txt".
# Правильно было бы использовать кавычки: [ -f "$file" ]

2. Поддержка расширенных операторов

[[ ]] поддерживает дополнительные операторы, такие как &&, ||, =~ (для регулярных выражений) и == с шаблонами (pattern matching), в то время как [ ] требует использования флагов -a, -o и не поддерживает регулярные выражения напрямую.

# Регулярные выражения с =~
if [[ "$string" =~ ^[0-9]+$ ]]; then
    echo "Строка состоит только из цифр."
fi
# В [ ] это не поддерживается.

# Логические операторы
if [[ -f "$file" && -r "$file" ]]; then
    echo "Файл существует и доступен для чтения."
fi
# В [ ] пришлось бы писать: [ -f "$file" -a -r "$file" ]

3. Сравнение строк

В [[ ]] операторы == и != поддерживают шаблоны (подобно globbing), а в [ ] они работают только как обычные строковые сравнения (если не используется test в режиме совместимости).

string="hello world"
if [[ $string == hello* ]]; then
    echo "Строка начинается с 'hello'."
fi
# В [ ] это не сработает как шаблон: [ "$string" == "hello*" ] сравнивает строки буквально.

4. Безопасность и обработка ошибок

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

var=""
if [[ $var == "" ]]; then
    echo "Переменная пуста."
fi
# Корректно работает.

if [ $var == "" ]; then
    echo "Переменная пуста."
fi
# Может вызвать ошибку, потому что [ видит пустой аргумент. Правильно: [ "$var" = "" ]

5. Производительность

[[ ]] является встроенным оператором оболочки (shell keyword), поэтому работает немного быстрее, чем [ ], который является встроенной командой (builtin command). В контексте скриптов разница обычно незначительна, но в больших циклах может быть заметна.

Когда что использовать

  • [[ ]] — предпочтительный выбор для скриптов на Bash, так как он предоставляет больше функций, безопаснее и читаемее. Используйте его, если не требуется строгая POSIX-совместимость.
  • [ ] — используйте только для написания переносимых скриптов, которые должны работать в оболочках, совместимых с POSIX (например, dash), или в очень старых системах, где Bash может отсутствовать.

Сводная таблица различий

Критерий[ ] (test)**[[ ]]**
ТипВстроенная командаКлючевое слово оболочки
POSIXДаНет (расширение Bash)
Логические операторы-a (И), -o (ИЛИ)&& (И), `
Регулярные выраженияНе поддерживаетПоддерживает (=~)
Шаблоны (globbing)Нет (только строки)Да (==, !=)
Разбиение словДа (нужны кавычки)Нет (безопаснее)
ПроизводительностьМедленнееБыстрее
Обработка пустых переменныхПроблематична (требует кавычек)Безопасна

Примеры кода

#!/bin/bash

# Пример 1: Безопасное сравнение с пустой переменной
unset var
if [[ $var == "" ]]; then
    echo "var пуста или не установлена (без ошибки)."
fi

# Пример 2: Регулярное выражение
email="user@example.com"
if [[ $email =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
    echo "Валидный email."
fi

# Пример 3: Комбинирование условий
file="/path/to/file"
if [[ -f "$file" && ( -r "$file" || -w "$file" ) ]]; then
    echo "Файл существует и доступен для чтения или записи."
fi

# Пример 4: POSIX-совместимый вариант с [ ]
if [ -f "$file" -a \( -r "$file" -o -w "$file" \) ]; then
    echo "То же самое, но менее читаемо."
fi

В современных скриптах на Bash рекомендуется использовать [[ ]] из-за его преимуществ в безопасности и функциональности, резервируя [ ] только для случаев, когда необходима переносимость.