Проверка условий в Bash
Продолжаем изучение Bash и в эот раз мы поговорим о проверкиусловий. Так если Вы помните в материале Изучаем BASH (Инструкции)
мы говорили о том, что инструкция if-then работает именно с командами, а не с условиями и при работе с ними возвращает статус ноль в случае успеха выполнения команды, однако необходим какой-то способ выполнять проверку условий в Bash и такой способ разумеется существует.
Ну давайте сразу перейдем к примеру, а до этого уясним, что существует команда test, которая обрабатывает условия по сравнению строк, чисел и файлов , а выглядит она примерно так:
#!/bin/bash
var1=10
var2=15
if [ $var1 -le $var2 ]
then
echo «10
fi
Ну что же дальше лучше всего привести несколько примеров по работе со сравнениями, а так же указать операторы по сравнению файлов, папок и чисел.
Операторы BASH
Работа с числами
#!/bin/bash
var1=15
if [ $var1 -le 1 ]
then
echo «Истина»
else
echo «Ложь»
fi
Работа со строками
st11 равно str2
str1 иммет длину больше 0
str2 имеет длину 0
#!/bin/bash
str1=qwert
str2=qwerty
if [ $str1 = $str2 ]
then
echo «Истина»
else
echo «Ложь»
fi
#!/bin/bash
str1=
if [ -z $str1 ]
then
echo «Истина»
else
echo «Ложь»
fi
3) В этом примере показывается как не надо делать сравнение при операторе больше или меньше, так как в данном случае они выполняют перенаправление.
#!/bin/bash
str1=qwert
str2=qweeeeeeeeeee
if [ $str1 > $str2 ]
then
echo «Истина»
else
echo «Ложь»
fi
Для правильного сравнения необходимо произвести экранирование оператора.
#!/bin/bash
str1=qwert
str2=qwertwww
if [ $str1 \> $str2 ]
then
echo «Истина»
else
echo «Ложь»
fi
Работа с файлами
проверка на существования файла и на того, что он является каталогом
существует файл или каталог
существет и это файл
существует и стоит атрибут чтения
существует и не пустой
существет и запись
существет и выполение
файл существует и принадлежит текущему пользователю
существует и его группа такая же как у текущего пользователя
files1 -nt files2
более новый чем files2
files1 -ot files2
более старый чем
#!/bin/bash
cat1=/tmp/cat
# Проверяем существет ли каталог /tmp/cat
if [ -e $cat1 ]
then
echo «Каталог $cat1 существует»
if [ -w $cat1/1234 ]
then
echo «Файл существует и Предназначен для записи»
else
echo «файл не существует — создаем его»
date > $cat1/1234
fi
if [ -O $cat1/1234 ]
then
echo «Файл принадлежит текущему пользователю»
date >> $cat1/1234
echo «Добавили данные»
else
echo «Файл не текущего пользователя»
fi
else
echo «Каталог не существует»
fi
Существют еще пара оперторов, которые не заменимы в BASH.
&& — Оператор «И»
|| — Оператор «ИЛИ»
В предыдущий пример достаточно внести не большые изменения и все станет ясно.
if [ -O $cat1/1234 ] && [ -G $cat1/1234 ]
then
echo «Файл принадлежит текущему пользователю и имеет одинаковые группы»
else
echo «Файл не текущего пользователя и не одинаковы группы»
Двойные скобки BASH
Двойные круглые скобки
Помните операторы работы с числами, когда для сравнения чисел меньше, больше и т.д. вы вместо знаков использовали -ge, -ne и т.д.
При помощи двойных круглых скобок можно производить любое матиматическое выражения как присваивания так и сравнения.
#!/bin/bash
if (( 10 ** 2 > 10 ))
then
echo «true»
else
echo «false»
fi
Двойные квадратные скобки
Давайте возьмем какой-либо старый пример и посмотрим разницу:
#!/bin/bash
cat1=/root
if [ -O $cat1/1234 ] && [ -G $cat1/1234 ]
then
echo «Файл принадлежит текущему пользователю и имеет одинаковые группы»
else
echo «Файл не текущего пользователя и не одинаковы группы»
fi
Альтернативой будет такое выражение:
1)
#!/bin/bash
cat1=/root
if [[ -O $cat1/1234 && -G $cat1/1234 ]]
then
echo «»
else
echo «»
fi
ЕЩЕ несколько примеров:
2) Если текущий рабочий каталог /tmp И принадлежит той же группе, что и пользователь Тогда создаем файл Если нет тогда переходим в /tmp и создаем файл.
#!/bin/bash
pwdd=/tmp
if [[ $PWD == $pwdd && -G $pwdd ]]
then
touch files2
else
cd $pwdd
touch files3
fi
Так же стало возможным производить сопоставление с шаблоном.
4) Если текущий каталог /home/X* где после * все что угодно И текщий пользователь начинается на X, Тогда выполнить команду ls -al
#!/bin/bash
pwdd=/home/XXX
if [[ $PWD = /home/X* && $USER == X* ]]
then
ls -al
else
echo «false»
fi
Источник
В чем разница между двойными и одиночными квадратными скобками в bash?
Мне просто интересно, что именно разница между
, кроме того, последний является posix-совместимым, найденным в sh, а первый является расширением, найденным в bash.
5 ответов
Есть несколько отличий. На мой взгляд, некоторые из наиболее важных:
- [ встроен в Bash и многие другие современные оболочки. Встроенный [ похож на test с дополнительным требованием закрытия ] . Встроенные [ и test ) имитируют функциональные возможности /bin/[ и /bin/test ) вместе с их ограничениями что скрипты будут обратно совместимы. Исходные исполняемые файлы по-прежнему существуют в основном для соответствия POSIX и обратной совместимости. Выполнение команды type [ в Bash означает, что [ интерпретируется как встроенный по умолчанию. (Примечание: which [ ищет только исполняемые файлы в PATH и эквивалентен типу type -p [ )
- [[ не является совместимым, он обычно не будет работать с любыми пунктами /bin/sh ). Таким образом, [[ ] — это более современный вариант Bash /Zsh /Ksh.
- Поскольку [[ встроен в оболочку и не имеет устаревших требований, вам не нужно беспокоиться о разбиении слов на основе переменной IFS ), чтобы испортить на переменные, которые оценивают строку с пробелами. Поэтому вам не нужно вставлять эту переменную в двойные кавычки.
По большей части, остальное — всего лишь несколько более симпатичный синтаксис. Чтобы увидеть больше различий, я рекомендую эту ссылку для ответа на часто задаваемые вопросы: В чем разница между тестом, [и [ ? . На самом деле, если вы серьезно относитесь к сценарию bash, я рекомендую прочитать всю wiki , включая FAQ, Ловушки и Руководство. Раздел теста из раздела руководства объясняет эти различия, а также почему автор (ы) думают, что [[ ] — лучший выбор, если вам не нужно беспокоиться о том, чтобы быть портативным. Основные причины:
- Вам не нужно беспокоиться о цитировании левой части теста, чтобы он действительно читался как переменная.
- Вам не нужно бежать меньше и больше с обратными косыми чертами, чтобы их не оценивали как входное перенаправление, что может действительно испортить некоторые вещи путем перезаписи файлов. Это снова возвращается к [[ ], являющемуся встроенным. Если [(test) является внешней программой, оболочка должна была бы сделать исключение в том, как она оценивает и > только в том случае, если /bin/test , что на самом деле не имеет смысла.
[] — bash Встроенные
[[]] являются bash Ключевые слова
Ключевые слова: Ключевые слова очень похожи на встроенные, но главное отличие в том, что к ним применяются специальные правила синтаксического анализа. Например, [является bash builtin, а [[является ключевым словом bash. Они оба используются для тестирования материала, но поскольку [[является ключевым словом, а не встроенным), это дает несколько особых правил синтаксического анализа, которые делают его намного проще:
Первый пример возвращает ошибку, потому что bash пытается перенаправить файл b в команду [a]. Второй пример фактически делает то, что вы ожидаете от него. Символ 29 декабря 2010, 22:42:25
Различия в поведении
Протестировано в Bash 4.3.11:
POSIX vs Расширение Bash:
регулярная команда против магии
[ — просто регулярная команда со странным именем.
] — это просто аргумент [ , который предотвращает использование дополнительных аргументов.
Ubuntu 16.04 фактически имеет исполняемый файл для него в /usr/bin/[ , предоставленный coreutils, но встроенная версия bash имеет приоритет.
Ничто не изменяется в том, как Bash анализирует команду.
В частности, перенаправляется, && и || объединяет несколько команд, ( ) генерирует подоболочки, если не выполняется с помощью \ , а расширение слова происходит, как обычно.
[[ X ]] — это единственная конструкция, которая заставляет X анализироваться магически. , && , || и () , и правила разделения слов отличается.
Существуют и другие отличия, такие как = и =
- [[ a : лексикографическое сравнение
- [ a \ : То же, что и выше. \ , либо перенаправление, как и для любой другой команды. Расширение Bash.
- Я не мог найти альтернативу POSIX для этого: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-less-than-or-equal
- [[ a = a && b = b ]] : true, logical и
- [ a = a && b = b ] : синтаксическая ошибка, && анализируется как разделитель команды AND cmd1 && cmd2
- [ a = a -a b = b ] : эквивалентно, но не рекомендуется POSIX
- [ a = a ] && [ b = b ] : рекомендация POSIX
- [[ (a = a || a = b) && a = b ]] : false
- [ ( a = a ) ] : синтаксическая ошибка, () интерпретируется как подоболочка
- [ \( a = a -o a = b \) -a a = b ] : эквивалентно, но () устарел POSIX
- ([ a = a ] || [ a = b ]) && [ a = b ] Рекомендация POSIX
- x=’a b’; [[ $x = ‘a b’ ]] : true, кавычки не нужны
- x=’a b’; [ $x = ‘a b’ ] : синтаксическая ошибка, расширяется до [ a b = ‘a b’ ]
- x=’a b’; [ «$x» = ‘a b’ ] : equal
- [[ ab = a? ]] : true, потому что он соответствие шаблонов ( * ? [ являются магии). Не расширяет glob для файлов в текущем каталоге.
- [ ab = a? ] : a? расширяется. Так может быть правдой или ложью в зависимости от файлов в текущем каталоге.
- [ ab = a\? ] : false, а не расширение glob
- = и == одинаковы как для [ , так и для [[ , но == является расширением Bash.
- printf ‘ab’ | grep -Eq ‘a.’ : эквивалент POSIX ERE
- [[ ab =
‘ab?’ ]] : false, теряет магию с помощью »
[[ ab? =
ab? ]] : true, POSIX расширенное регулярное выражение match, ? не раскрывает glob
[ a =
a ] : синтаксическая ошибка
Рекомендация
Я предпочитаю всегда использовать [] .
Существуют эквиваленты POSIX для каждой конструкции [[ ]] , которую я видел.
Если вы используете [[ ]] , вы:
- потерять переносимость
- заставляет читателя изучить тонкости другого расширения bash. [ — это просто регулярная команда со странным именем, никаких специальныхсемантика.
Основываясь на быстром просмотре соответствующих разделов справочной страницы, основное отличие заключается в том, что операторы == и != соответствуют шаблону, а скорее чем буквальная строка, а также что существует оператор сравнения =
Одиночная скобка , т. е. [] — оболочка POSIX, соответствующая заключению условного выражения.
Двойные скобки , т. е. [[]] — расширенная (или дополнительная) версия стандартной версии POSIX, это поддерживается bash и другими оболочками (zsh, ksh) .
В bash для численного сравнения мы используем eq , ne , lt и gt , с двойными скобками для сравнения мы можем использовать == , != , и > буквально.
- [ является синонимом команды test. Даже если он встроен в оболочку, он создает новый процесс.
- [[ ] — новая улучшенная версия, которая является ключевым словом, а не программой.
Источник
Проверка условий в bash
Это немного подправленная выдержка из этой статьи .
Скобки
[ — является специальной встроенной командой test воспринимающей свои аргументы как выражение сравнения или файловую проверку […..].
[[ — расширенный вариант от «[«, является зарезервированным словом, а не командой, его bash выполняет как один элемент с кодом возврата. Внутри «[[….]]» разрешается выполнение операторов &&, || которые приводят к ошибке в обычных скобках «[….]» тем самым вариант с двойной скобкой более универсален.
(( — является арифметическими выражениями, которое так же возвращают код 0. Тем самым такие выражения могут участвовать в операциях сравнения.
Приведу список логических операторов, которые используются для if|then|else:
-z – строка пуста
-n – строка не пуста
=, ( == ) – строки равны
!= – строки неравны
-eq – равно
-ne – неравно
-lt,( ) – больше
-ge,(>=) — больше или равно
! — отрицание логического выражения
-a,(&&) – логическое «И»
-o,(||) -логическое «ИЛИ»
Конструкции простой проверки if|then
Другими словами:
если проверяемое_выражение_или_команды_верны; то выполняем команды закрываем если
Пример 1
Часто встречается в скриптах проверка — «существует ли файлы или каталоги» на их примере покажу работу
Пример 2
$HOME/.bashrc – путь до файла
echo – печатает сообщение в консоль
Пример 3
&& — логическое «и», если первый путь «истина» проверяем второй, если он тоже «истина», то выполняем команды (echo)
-f – ключ проверки на существования файла (о них чуть ниже)
Конструкции простой проверки if|then|else
если проверяемое_выражение_или_команды_верны; то команды 1 иначе команды 2 закрываем если
Пример 4
Возможно не лучший пример, нас интересует именно ответ 0 или 1. В результате печатается в консоль «Тест» и «0» потому что команда «echo Тест» успешна и это «истина».
Намерено допустите ошибку изменив echo, в результате получите «1» и сообщение о том что «команда echo не существует» и это «ложь».
Примеры «существуют ли файл?»
Пример 5
Если файл bashrc существует, то печатает в консоль «Файл существует!», иначе печатает «Файл не существует!»
Поиграйте с именем проверяемого файла
Пример 6
Ключи к файлам и каталогам
[ -ключ “путь” ]
[ -e “путь каталогу_или_файлу”] – существует ли файл или каталог.
[ -r “путь к файлу/каталогу”] – доступен ли файл/каталог для чтения.
[ -f “путь к файлу/каталогу”] – существует ли файл.
[ -d “путь к каталогу”] – существует ли каталог.
Полное описание возможных применений различных скобок, правильное расставление кавычек уходит далеко от темы, поэтому могу посоветовать обратится к руководству Advanced Bash Scripting
Арифметика
Пример 7
Если оператор > использовать внутри [[….]], он рассматривается как оператор сравнения строк, а не чисел. Поэтому операторам > и
Пример 8
Использование команды test, коей являются квадратные скобки. Если «3» меньше «6» печатаем «Да».
Можно использовать и двойные квадратные скобки, это расширенный вариант команды test, эквивалентом которой является «[ ]». Если «3» меньше «6» печатаем «Да».
Пример 9
Используем двойные квадратные скобки, потому что применяем оператор «&&». Если первое выражение 2 = 2 (истина) тогда выполняем второе, и если оно тоже 2=2 (истина), печатаем «Верно»
Если первое выражение 2 = 2 (истина) тогда выполняем второе, и если переменная «b» не равна двум (ложь), печатаем «Не верно»
Можно конечно сделать проще, нам главное понять принцип if|then и else, не стесняйтесь менять, подставляя свои значения.
Вложение нескольких проверок
Bash позволяет вкладывать в блок несколько блоков
Построения многоярусных конструкций
Для построения многоярусных конструкции, когда необходимо выполнять множество проверок лучше использовать elif — это краткая форма записи конструкции else if.
Источник