Почему лишние условия убивают читаемость в Bash
Всем привет. Сегодня хочу поговорить о культуре написания условий bash. Точнее, об использовании отрицаний (НЕ).
читать первым в телеграм читать первым в макс
Поводом послужила конструкция, которую я нашел при изучении одного скрипта:
if [[ ! -f "$file" || ! -r "$file" || ! -w "$file" ]];then
echo "Ошибка: Файл отсутствует или нет прав на чтение/запись"
# exit 1
fi
Расшифруем:
! -f "$file" - НЕ регулярный файл (возможно каталог, устройство, или вообще ничего).! -r "$file" - у файла НЕт прав на чтение.! -w "$file" - у файла НЕт прав на запись.
Условия объединены по ИЛИ, значит если выполнится какое-либо - будет ошибка.
С точки зрения логики - все правильно, но у меня лично в глазах рябит от количества палок.
👆 На мой взгляд, отрицания сильно осложняют понимание.
Вспоминаем, что:
! A || ! B эквивалентно ! [ A && B ]
! A && ! B эквивалентно ! [ A || B ]
👆 И помним, что пробелы в условиях bash критически важны.
Таким образом, конструкцию можно переписать, с сохранением функциональности:
if ! [[ -f "$file" && -r "$file" && -w "$file" ]];then
echo "Ошибка: Файл отсутствует или нет прав на чтение/запись"
# exit 1
fi
Расшифруем:
НЕ (файл регулярный И есть права на чтение И есть на запись). В этой конструкции тоже есть отрицание, но оно уже одно! Конструкцию можно привести к еще более человеческому виду:
if [[ -f "$file" && -r "$file" && -w "$file" ]];then
:
else
echo "Ошибка: Файл отсутствует или нет прав на чтение/запись"
# exit 1
fi
Здесь отрицание заменено переносом тела if в тело оператора else.
“:” необходимо, потому что между if и else должен быть хотя бы один оператор (в данном случае “:” эквивалент оператора true или nop.
Можно записать и:
if [[ -f "$file" && -r "$file" && -w "$file" ]];then :
else
echo "Ошибка: Файл отсутствует или нет прав на чтение/запись"
# exit 1
fi
👆 Обратите внимание на “:” после then
Но на мой взгляд, в данном случае, читаемость несколько ухудшится.
Если при объединении по ИЛИ первый операнд ИСТИНА, то остальные даже проверяться не будут.
При объединении по И все наоборот: остальные проверяться не будут - если первый операнд ЛОЖЬ.
Всем работы без багов.
