Изучаем Bash: Команда test и ее аналоги. Проверка файлов и сравнение строк
После небольшой паузы, я продолжаю писать статьи на тему Bash и сегодня мы поговорим о команде test и ее аналогах. Разбирать одну теорию мы не будем и давайте сразу взглянем на скрипт и разберемся на его примере.
file=/etc/fstab # Объявляем переменную
if test -e $file # Используем команду test
echo «Файл fstab найден.»
echo «Что-то нету такого файла»
Как мы видим, мы использовали знакомые нам операторы if / then , которые я уже описывал ранее.
После оператора if стоит команда test которая и и производит проверку нашего файла, который мы объявили в переменной. Также, команду test мы использовали с опцией «-e», данная опция возвращает значение «true», если файл найден.
В случае «true» запускается оператор then и выводит строку echo, если же файл не найдет, что означает «false», то запускается оператор else и выводит сообщение «Что-то нету такого файла».
Теперь давайте рассмотрим аналоги команды test. Тот же скрипт, только вместо test используем другие команды:
file=/etc/fstab # Объявляем перменную
if /usr/bin/[ -e $file ] # Используем команду «[«, также мы закрыли ее правой ], потому bash требует ее наличие
echo «Файл fstab найден.»
echo «Что-то нету такого файла»
Использовали вместо команды test, команду «[» с закрытой правой «]». Вообще, старые версии bash не требовали наличие правой закрывающейся ]. Теперь это необходимо, чтобы избежать ошибок.
Я рекомендую вместо [ ] использовать конструкцию [[ ]]:
file=/etc/fstab # Объявляем перменную
if [[ -e $file ]] # Используем конструкцию [[ ]]
echo «Файл fstab найден.»
echo «Что-то нету такого файла»
Почему [[ ]] лучше, чем [ ]? Потому что внутри [[ ]] вы можете использовать например такие операторы, как: &&, ||, , в то время как внутри [ ] будут сообщения об ошибках.
Кстати, вы можете использовать [ ] и [[ ]] без if / then / else. Те команды как бы заменяют данные операторы:
[[ «$var1» -ne «$var2» ]] && echo «$var1 не равно $var2»Давайте разберем, что мы тут написали.
Итак, мы объявили две переменные var1 и var2 с числовыми значениями. Далее, мы вместо if / then / else использовали [[ ]], «-ne», которая находится между «$var1» и «$var2» означает «не ровно». Оператор && — and (и).
Вот так вот 🙂 Любые вопросы приветствуются! 🙂 С следующих статьях мы рассмотрим операции сравнения чисел и строк.
у меня вопрос, а арифметические операции делать можно в [[ ]]?
нет, для этого существует оператор (( )), о котором я напишу обязательно 🙂
спасибо! :=) мне это нужно :=)
Так. Вы хотите сказать что, пример, конвеер cat file | grep 123 лучше всего помещать в [[ ]] ?
Эксперт — зто человек, который совершил все возможные ошибки в очень узкой специальности.
это у тебя кусок кода или это весь скрипт? В этом случае не надо, потому что у тебя тут нету ни какого сравнения, не тестирования. обычный вывод информации и поиск grep. Мое мнение 🙂
Конечно это вырезка из скрипта, придуманная на ходу, но у меня реально есть скрипты с похожими условиями. Условия такие:
[ cat file | grep 123 ] ; then
rm file
fi
продолжение скрипта допустим break
Эксперт — зто человек, который совершил все возможные ошибки в очень узкой специальности.
в твоем случае ты можешь вместо [ ], использовать оператор if, то есть:
if cat file | grep 123; then
rm file
fi
действие будет аналогичным 🙂
Едрен батом, прошу прощения. Я не верно написал
[ `cat file | grep 123` = 123 ]
Но ваш способ кажется еще лучше, попробую.
Эксперт — зто человек, который совершил все возможные ошибки в очень узкой специальности.
что значит grep 123 = 123 и зачем тут используешь одинарные ковычки?
P.S. Александр, я настолько простой, что лучше ко мне на «ты» 😉
Все просто. любую команду имеющую параметры через пробел нужно помещать в « иначе shell не понимает. А вообще смысл у моего примера такой: если в текстовом файле появится строчка имеющая 123, это для примера, на самом деле в реальном скрипте ищется #####, так вот если это в файле есть, то файл не обрабатывать, а удалить и перейти к следующему циклу. Возможно я забыл еще что-то но смысл такой и он у меня работает. Есть правда у меня косяк: если попадется 2 строчки с тем что я ищю, то скрипт пишет: test argument expected и завершается полность, пока это еще не побарол, не могу понять почему ему 2 значения в поиске не устраивает, благо такое случается раз в пол года.
А я понял. Можно либо в ` ` либо в [[ ]] вот и весь ответ. Блин как обычно не дочитал совсем немного. Спасибо, но я привык «.
Эксперт — зто человек, который совершил все возможные ошибки в очень узкой специальности.
я имел ввиду, почему два раза у тебя 123 в скрипте? 🙂
Как понять зачем, если условие равно то, если нет то, не пойму в чем собственно вопрос.
Эксперт — зто человек, который совершил все возможные ошибки в очень узкой специальности.
отличная работа, Максим, я тоже присоединюсь к написанию статей по bash, хорошая тема
Команда test
Предназначена для проверки типа файла и сравнения чисел и строк. Возвращает код возврата 0 (истина) или 1 (ложь) в зависимости от вычисления выражения. Выражения могут быть как унарными, так и бинарными.
Для сокращения кода сценария используют парный оператор [ как синоним test . Парный оператор требует пробела между скобками потому, что [ (скобка) является командой оболочки.
Проверка типа файла
- -d file — истина, если file существует и является каталогом
- -e file — истина, если file существует
- -f file — истина, если file существует и является обычным файлом
- -r file — истина, если file существует и доступен для чтения
- -s file — истина, если file существует и имеет размер больше, чем ноль
- -w file — истина, если file существует и доступен для записи
- -x file — истина, если file существует и доступен для выполнения
- -L file — истина, если file существует и является символьной ссылкой
- file1 -nt file2 — истина, если file1 новее (дата модификации), чем file2
- file1 -ot file2 — истина, если file1 старее, чем file2
Сравнение строк
- -z string — истина, если длина string равна нулю
- -n string — истина, если длина string не ноль
- string1 = string2 — истина, если строки равны
- string1 != string2 — истина, если строки не равны
Сравнение целых чисел
- число1 -eq число2 — истина, если число1 равно число2
- число1 -gt число2 — истина, если число1 больше число2
- число1 -ge число2 — истина, если число1 больше или равно число2
- число1 -lt число2 — истина, если число1 меньше число2
- число1 -le число2 — истина, если число1 меньше или равно число2
- число1 -ne число2 — истина, если число1 не равно число2
Операции AND и OR
- expr1 -a expr2 — истина, если оба выражения expr1 и expr2 истина (операция AND)
- expr1 -o expr2 — истина, если хотя бы одно из выражений expr1 или expr2 истина (операция OR)
- ! expr — истина, если выражение expr ложно
В условном выражении команды test можно использовать круглые скобки, чтобы изменить порядок вычисления, но их нужно экранировать:
« [[…]] » — расширенный вариант от « […] », оболочка выполняет его как один элемент с кодом возврата. Внутри « [[…]] » разрешается выполнение операторов && , || которые приводят к ошибке в обычных скобках « […] ».
Функции сравнения и тестирования в Bash
Пояснения по конструкциям test , [, [[, ((, и if-then-else
Серия контента:
Этот контент является частью # из серии # статей: Подсказки по Linux
Этот контент является частью серии: Подсказки по Linux
Следите за выходом новых статей этой серии.
Bash shell сгодня доступен на многих Linux® и UNIX® системах и является по умолчанию основным shell-кодом в Linux. Bash предоставляет широчайшие возможности для программирования, в том числе расширенное число фунций для тестирования типов файлов и атрибутов, равно как и всяческие возможности для сравнения строк и чисел, доступные в большинстве языков программирования. Для продвинутого пользователя shell крайне важно разбираться в различных типах тестов и знать то, что shell может интерпретировать некоторые операторы как свои метасимволы. Эта статья представляет собой извлечение из руководства developerWorks LPI exam 102 prep: Shells, scripting, programming, and compiling (exam 102 prep: Shell-коды, написание скриптов, программирование и компилирование) и показывает, как разобраться в использовании операций проверки и сравнения в Bash shell.
Здесь показано, что представляют из себя shell-функции проверки и сравнения, и показано как повысить программные возможности shell. Вероятно, вы уже познакомились с простой логикой shell при использовании операторов && и ||, которые позволяют выполнять команду в зависимости от того, произошла ли ошибка при выполнении предыдущей команды или нет. Вы увидите здесь, как расширить применение этих базовых приемов для решения более сложных задач shell-программирования.
Тесты
При работе с любым языком программирования, после того, как вы научитесь приписывать значения переменным и передавать параметры, вам понадобится знать, как тестировать эти значения и параметры. В shell-кодах тесты, как и все прочие команды определяют статус выдачи. При этом выражение test даже является встроенной командой!
test и [
Встроенная команда test возвращает 0 (True) или 1 (False), в зависимости от определения выражения expr. Также вы можете использовать квадратные скобки: test expr и [expr] представляют из себя эквивалентные выражения. Вы можете просмотреть возвращаемое значение с помощью $? ; вы можете использовать возвращаемое значение с помощью && и ||; вы можете также протестировать это значение с помощью различных условных конструкций, которые рассматриваются далее в этом руководстве.
Листинг 1. Некоторые простые тесты
В первом примере листинга 1, оператор -gt выполняет арифметическое сравнение двух строковых значений. Во втором примере с помощью альтернативной тестовой формы [ ] оценивается (не)равенство двух строк. В последнем примере значение переменной HOME проверяется с целью увидеть, папка это или нет, при этом используется унарный оператор -d .
Вы можете сравнивать два числовых значения с помощью операторов -eq , — ne , -lt , — le , — gt , or — ge , означающих соответственно «равно», «неравно», «меньше», «меньше либо равно», «больше» и «больше либо равно».
Вы можете сравнивать строки на равенство и неравенство, а также на то, будет ли первая строка поставлена до или после второй при сортировке. Для всего этого используются, соответственно, операторы = , != , и > . Унарный оператор -z проверяет, не пуста ли строка, тогда как оператор -n или вообще отсутствие оператора возвращает True если строка не пуста.
Замечание: операторы и > также используются shell для перенаправления. Этого надо избегать с помощью \ или \> . Листинг 2 содержит в себе еще несколько примеролв тестов строк. Проверьте, как они работают.
Листинг 2. Некоторые тесты строк
Некоторые наиболее часто используемые тесты файлов показаны в таблице 1. Результат теста это True, если тестируемый файл существует и имеет указанные характеристики.
Оператор | Характеристика |
---|---|
-d | Папка |
-e | Существует (также -a) |
-f | Стандартный файл |
-h | Символьная ссылка (также -L) |
-p | Именованный канал |
-r | Доступный вам для чтенения |
-s | Не пустой |
-S | Сокет |
-w | Доступный вам для записи |
-N | Был изменен со времени последнего прочтения |
Кроме представленных выше унарных тестов существуют бинарные операторы для сравнения двух файлов. Они показаны в таблице 2.
Оператор | True если |
---|---|
-nt | Проверяет, является ли file1 более новым, чем file 2. Для этого и для следующего сравнения используется дата последнего изменения. |
-ot | Проверяет, является ли file1 более старым, чем file 2. |
-ef | Проверяет, является ли file1 жесткой ссылкой на file2. |
Некоторые другие тесты позволят вам проверять другие вещи, например права доступа к файлу. Для более детального ознакомления посмотрите страницы с руководствами по bash или используйте команду help test , чтобы получить краткую информацию по встроенной команде test. Вы можете использовать команду help и для других встроенных команд.
Оператор -o позволяет вам тестировать различные опции shell, которые могут быть установлены командой set -o option , которая возвращает True (0), если опция установлена и False (1) в противном случае, как показано в листинге 3.
Листинг 3. Тестирование опций shell
Наконец, опции -a и -o соединяют выражения как логическое И и ИЛИ соответственно, а унарный оператор ! делает смысл теста противоположным. Вы можете использовать круглые скобки, чтобы группировать выражения и выполнять операции не по порядку установленного по умолчанию старшинства. Помните, что shell, как правило, запускает выражение в скобках в электронной подоболочке, поэтому вам придется вместо просто скобок писать \( и \) или заключать описанные выше операторы в одиночные или двойные кавычки. Листинг 4 показывает применение к выражению законов де Моргана.
Листинг 4. Конъюнкция и дизъюнкция тестов
Команда test предоставляет широчайшие возможности, но является несколько неудобной в использовании из-за необходимости делать переходы в коде с помощью \ и из-за различиях в сравнениях строк и чисел. К счастью, bash располагает двумя другими способами тестирования, которые покажутся более естественными для тех, кто знаком с синтаксисом C, C++ или Java®.
Составная команда (( )) оценивает арифметическое выражение и устанавливает статус выдачи равный 1, если выражение равно 0, или статус выдачи равный 0, если выражение имеет ненулевое значение. Вам ненужно ставить \ перед операторами между (( и )) . Арифметика работает с целыми числами. Деление на 0 вызывает ошибку, но переполнение этого не делает. Вы выполняете обычные для языка C арифметические, логические и побитовые операции. Команда let также может запускать одно или несколько арифметических выражениий. Она обычно используется для того, чтобы приписывать значения арифметическим переменным.
Листинг 5. Присваивание и тестирование арифметических выражений
Как и в случае с (( )) , составная команда [[ ]] позволяет вам использовать более естественный синтаксис для тестирования имен файлов и строк. Вы можете объединять тесты, которые разрешены для команды test с помощью круглых скобок и логических операторов.
Листинг 6. Использование составного оператора [[
Составной оператор [[ также может делать сопоставление с образцом для строк в тех случаях, когда используются операторы = или != . Сопоставление происходит похожим на универсализацию файловых имен образом, с помощью группового символа, как это показано в листинге 7.
Листинг 7. Тесты с [[ и групповым символом
Вы можете даже делать арифметические тесты внутри составных операторов с [[ , но делайте это с осторожностью. Если только они не находятся внутри составного оператора (( , операторы и > будут сравнивать операнды как строки и проверять их порядок в зависимости от текущей последовательности сортировки. Листинг 8 дает некоторые примеры этого.
Листинг 8. Осуществление арифметических тестов с помощью [[
Условные конструкции
С помощью описанных выше тестов и операторов контроля && и || вы можете решить немало задач программирования. Кроме всего этого bash включает в себя и более привычные конструкции с if, then, else и с case. Когда вы ознакомитесь с ними, можно будет перейти к конструкциям с циклами, что существенно расширит набор средств, которые вы сможете использовать.
Консрукции с if, then, else
Команда if в bash является составной командой которая проверяет выдаваемое значение теста или команды ( $? ), а затем ветвится в зависимости от того равно ли это проверяемое значение True (0) или False (не 0). Вышеописанные тесты возвращают только значения 0 или 1, но команды могут возвращать и другие значения. Больше вы узнаете об этом в руководстве LPI exam 102 prep: Shells, scripting, programming, and compiling (LPI exam 102 prep: Shell-коды, написание скриптов, программирование и компилирование.
Составная команда if в bash всегда содержит в себе предложение с then со списком команд которые должны быть выполнены, если тест или команда сразу после if возвращает 0. Команда if также может содержать одно или несколько предложений с elif , каждое из которых содержит в себе дополнительный тест и предложение с then и списком команд. Далее if может содержать завершающее предложение с else и списком команд, оторые надо выполнить, если ни изначальный тест, ни все тесты в предложениях с elif не дали результат True. Наконец, if завершается выражением fi , обозначающим окончание этой конструкции.
Используя все, что до сих пор было описано, вы можете построить простой калькулятор для вычисления арифметических выражений, как это показано в листинге 9.
Листинг 9. Вычисление выражений с if, then, else
Калькулятор использует выражение local , чтобы объявить x локальной переменной, которая используется только внутри функции mycalc . Функция let имеет несколько возможных опций, как и родственная ей функция declare . Для более детального ознакомления посмотрите страницы с руководствами по bash или используйте команду help let .
Как вы видели в листинге 9, необходимо ставить \ перед выражениями, содержащими метасимволы shell, такие как (, ), *, > и else и на два последних примера в листинге 9. Как вы видите, передавать xyz на вход функции mycalc не будет ошибкой, но такое выражение будет вычислено как 0. Эта функция не умеет определять значения символов в последнем примере и не может выдать пользователю предупреждение. Вы можете использовать тест для сопоставления строк с образцом, например
[[ ! («$*» == *[a-zA-Z]* ]]
(или в другой форме в зависимости от вашей локали), чтобы распознавать выражения, содержащие алфавитные символы, но это также не даст вам испльзовать шестнадцатиричную запись вводных данных (вы могли бы, например, записать 15 как 0x0f в шестнадцатиричной записи). Вообще shell позволяет использовать основания систем счисления вплоть до 64 (с использованием нотации base#value , где base — основание, а value — значение), так что вы можете использовать любой алфавитный символ, а также _ и @ для записи вводных данных. Для восьмеричной и шестнадцатеричной систем счисления используется обычная нотация со стоящими перед записью числа символамим 0 и 0x (или 0X) соответственно. Листинг 10 дает некоторые примеры этого.
Листинг 10. Числовые вычисления с различными основаниями системы счисления
Дальнейшая работа с вводными данными не будет затронута в данном руководстве, так что используйте этот калькулятор с осторожностью.
Выражение elif очень удобно. Оно помогает вам в написании скриптов тем, что усеньшает количество отступов в программе. Возможно, вас удивит выдача команды type для функции mycalc , показанная в листинге 11.
Листинг 11. Type mycalc
Конечно, вы можете делать арифметические вычисления с помощью shell просто с помощью команды $(( expression )) , где expression — арифметическое выражение, вместе с командой echo , как это показано в листинге 12. Для этого вам не нужно было изучать различные функции и тесты. Отметьте все же, что shell не интерпретирует обычным образом метасимволы, такие как *, когда они стоят внутри выражения типа (( expression )) или [[ expression ]] .
Листинг 12. Числовые вычисления в shell с помощью команд echo и $(( ))
Узнайте об этом больше
Если вы захотите узнать больше о Bash скриптинге в Linux, прочитайте руководство «LPI exam 102 prep: Shells, scripting, programming, and compiling (LPI exam 102 prep: Shell-коды, написание скриптов, программирование и компилирование)» из которого была взята данная статья, или обратитесь к другим ресурсам ниже. Не забудьте оценить эту страницу.
Ресурсы для скачивания
Похожие темы
- Оригинал этой статьи
- Просмотрите руководство «LPI exam 102 prep: Shells, scripting, programming, and compiling» (developerWorks, Январь 2007), чтобы найти более подробную информацию про кастомизацию Bash shell и скриптпнг в Linux. Оно является частью серии LPI exam prep tutorial series (Серии руководств LPI exam prep), которая рассказывает об основах Linux и помогает в подготовке к аттестации по специальности системного администратора.
- Прочитайте на developerWorks эти статьи, чтобы узнать о других способах работы с Bash:
- Bash в примерах, Часть 1: Основы программирования в Bourne again shell (bash)
- Bash в примерах, Часть 2: Дальнейшие основы bash программирования
- Bash в примерах, часть 3: О системе ebuild
- System Administration Toolkit: Get the most out of bash(Набор инструментов системного администрирования: добейтесь лучшего результата с bash)
- Working in the bash shell
- «Shell Command Language(Язык команд Shell)» — здесь вы найдете язык команд shell в формате The Open Group и IEEE.
- Найдите еще больше руководств для разработчиков Linux в разделе Linux на developerWorks .
- Скачайте испытываемое программное обеспечение IBM прямо с developerWorks.
Комментарии
Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.