Bash if then else примеры

.

Содержание

Bash в примерах. Часть вторая.

Еще больше основ программирования в bash

Обработка аргументов

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

В простом скрипте из предыдущей статьи мы использовали переменную «$1«, которая содержит первый аргумент командной строки при вызове скрипта.

Аналогично можно использовать «$2», «$3» и так далее для доступа ко второму, третьему… аргументам командной строки. Вот пример:

Обратите внимание, что в переменной «$0» содержится имя самого скрипта, который запущен из командной строки. А переменная «$#» содержит количество переданных скрипту аргументов. Использование фигурных скобок необязательно только для переменных состоящих из одной цифры (с $0 по $9). Попробуйте позапускать этот скрипт с разным числом аргументов и посмотрите как он работает.

Иногда необходимо сослаться сразу на все аргументы командной строки. Для этого в bash есть специальная переменная «$@«, которая содержит все аргументы переданные скрипту разделенные пробелами. Мы будем использовать эту переменную чуть позже при рассказе о циклах со счетчиком (конструкция «for»).

Управляющие конструкции bash

Если вы раньше программировали на процедурных языках, таких как Си, Паскаль, Перл и тому подобных, вам должны быть знакомы управляющие конструкции вроде «if», «for» и другие. В bash тоже есть все эти конструкции. В следующих разделах пособия я познакомлю вас с ними и покажу чем они отличаются от подобных конструкций из других языков программирования. Если вы раньше не программировали — не волнуйтесь. Материал будет изложен подробно и дополнен примерами, так что даже новичок в программировании сможет разобраться.

Оператор условного выбора «if»

Если вы раньше программировали на языке Си, то должны знать сколько требуется усилий чтобы определить какой из двух файлов был создан первым, например. А все из-за того, что в Си нет встроенных средств для такого рода сравнения. Вместо этого приходится использовать системный вызов stat() для каждого файла и затем сравнивать результат вручную. Но в bash есть встроенный механизм сравнения файлов, Поэтому узнать «доступен ли для чтения файл /tmp/myfile» настолько же просто как и узнать «превосходит ли значение переменной ‘myvar’ 4».

Привожу список наиболее часто употребляемых в bash операторов сравнения

Файлы

-a file
истинно если файл существует.
-d file
истинно если файл существует и является директорией.
-f file
истинно если файл существует и является обычным файлом.
-r file
истинно если файл существует и доступен для чтения.
-s file
истинно если файл существует и его размер больше 0.
-w file
истинно если файл существует и доступен для записи.
-x file
истинно если файл существует и является исполняемым.
file1 -nt file2
истинно если файл file1 новее чем file2 или file1 (в соответствии со временем последнего изменения) существует, а file2 нет.
file1 -ot file2
истинно если файл file1 старше чем file2 или file2 существует, а file1 нет.
file1 -ef file2
истинно если оба файла ссылаются на одно и то же устройство или инод.

Строки

-z string
истинно если строка имеет нулевую длину.
-n string
истинно если длина строки не нулевая.
string1 = string2
истинно если строки равны.
string1 != string2
истинно если не равны.
string1 < string2
истинно если строка 1 стоит в алфавитном порядке перед строкой 2.
string1 > string2
истинно если строка 1 стоит в алфавитном порядке после строки 2.

В следующих примерах показано как использовать оператор сравнения в конструкции «if»:

Квадратные скобки вычисляют условное выражение стоящее в них (это синоним встроенной функции bash — test).

Возвращаемый результат — 1 или 0 в зависимости от того выполняется условие или нет. в скобках может стоять несколько выражений, связанных логическими операторами «и» или «или«. Подробнее на странице справки help test.

В некоторых случаях одна и та же операция сравнения может быть сделана несколькими разными способами. Обе конструкции из следующего примера функционально идентичны:

В первой конструкции из предыдущего примера использована операция арифметического сравнения, а во втором — операция сравнения строк.

Тонкости при сравнении строк

В большинстве случаев, когда вы не заключаете строки и строковые переменные в двойные кавычки, это может привести к ошибке. Почему? Да потому что в строке может встретится пробел или символ табуляции, которые bash не сможет правильно обработать. Вот пример некорректного сравнения строк:

В этом примере, если значение переменной «$myvar» будет равно «foo», код будет работать как и ожидается и не печатать ничего. Но если значение переменной «$myvar» будет равно «foo bar oni», скрипт вызовет следующую ошибку:

После подстановки значения переменной, bash пытается произвести следующую операцию сравнения:

В этом случае bash не может правильно обработать сравнение строк содержащих пробелы, одна из которых не заключена в двойные кавычки.

Интерпретатор думает, что в квадратных скобках слишком много аргументов. После заключения переменной в двойные кавычки, ошибка не возникает и код работает так как мы задумали. Запомните, если вы возьмете в привычку заключать в двойные кавычки все строковые аргументы и переменные, то избежите множества ошибок подобных описанной выше. Вот исправленный кусок кода:

Этот код будет работать корректно и не преподнесет нам больше никаких неприятных сюрпризов.

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

Конструкция создания циклов «for»

Хорошо, с условными переходами разобрались, пора перейти к циклическим конструкциям.

Блог системного администратора

Начнем с управляющей конструкции «for«. Вот стандартный пример:

Что же именно произошло? Часть «for x» цикла «for» определяет переменную (называемую итератором) «$x», которая последовательно принимает значения «one», «two», «three», и «four» (по одному за один такт цикла). После присвоения каждого нового значения переменной «$x», выполняется тело цикла (код между словами «do» и «done»). В теле цикла мы выводим на печать значение переменной «$x». Заметим, что после слова «in» в конструкции «for» всегда стоит некий список. В данном примере мы указали четыре слова, но этот список может содержать имена файлов или даже шаблон (wildcard). В следующем примере показано как использовать шаблоны при инициализации итератора цикла:

Код этого цикла исполнится для каждого файла из /etc/ имя которого начинается с «r». Сначала bash найдет все такие файлы и заменит шаблон строкой /etc/rc0.d /etc/rc1.d /etc/rc2.d /etc/rc3.d /etc/rc4.d … /etc/rsyslog.d перед тем как приступить к выполнению цикла. В теле цикла для каждого файла из списка проверяется является ли этот файл директорией при помощи оператора «-d«. Если файл оказался директорией, рядом с его называнием печатается «(dir)».

В списке инициализации итератора можно использовать несколько шаблонов одновременно и даже переменные окружения:

Bash в этом примере подставляет значение переменной и раскрывает шаблоны. А затем копирует все файлы в заданную директорию.

До этого все примеры содержали шаблоны основанные на абсолютных путях, но можно использовать и относительные:

В этом примере bash раскрывает шаблон относительно текущей рабочей директории (не той в которой находится скрипт, а той которую показывает команда «pwd»). Поиграйтесь с этим скриптом, позапускайте его из разных директорий и посмотрите на результат.

Иногда может потребоваться запустить цикл по списку аргументов из командной строки. Вот как это делается:

В этом примере мы использовали переменную «$@» о которой говорили выше.

Арифметика в shell

Перед тем как приступить к разбору следующего вида циклической конструкции, научимся при помощи интерпретатора производить простые арифметические операции. Просто заключите арифметическое выражение в конструкцию «$(( ))» и bash посчитает ее значение. Вот несколько примеров:

Теперь, когда вы познакомились с вычислением арифметических выражений в shell, пришло время рассказать о циклических конструкциях «while» и «until».

Циклические конструкции с условиями («while» и «until»)

«while»–цикл исполняется пока выражение в квадратных скобках истинно. Он имеет следующий формат:

В следующем примере тело цикла исполняется ровно 10 раз:

После каждого выполнения кода тела цикла переменная «myvar» увеличивается на 1. Когда значение переменной становится равным 10, условие в квадратных скобках не выполняется и цикл прерывается.

«Until»–цикл очень похож на «while»–цикл: он повторяется пока выражение в квадратных скобках ложно.

Вот пример «until»–цикла по функциональности идентичного «while»–циклу из предыдущего примера:

Экстренный выход из цикла

Для экстренного выхода из «for», «while» или «until» цикла используется команда break. Для выхода из нескольких вложенных циклов — break N, где N — количество вложенных циклов.

В последнем примере: «while :» — бесконечный цикл. Двоеточие — это команда bash которая не делает ничего но всегда завершается успехом. Переменная $? содержит статус с которым завершилась последняя команда (подробнее о специальных переменных смотри man bash). В нашем случае код отличный от 0 обозначает что при скачивании файла произошла ошибка. Как только условие в квадратных скобках выполнено, интерпретатор переходит к исполнению команды стоящей после логического и (&&). Break прерывает выполнение цикла.

Предпоследнюю строку предыдущего примера можно заменить на знакомую нам условную конструкцию «if» (помним, что в bash одно действие можно сделать несколькими разными способами):

то же самое но через условную конструкцию:

Или в одну строку

Да, конструкции можно записывать в одну строку, только нужно поставить несколько разделяющих знаков «точка с запятой». Но не стоит привыкать к такой форме записи — это усложняет читаемость кода.

Команда–переключатель «case»

Конструкция условного перехода «case» может оказаться очень полезной. Вот пример ее использования:

В этом примере сначала происходит обработка строки в переменной «$x» — «${x##*.}». Как мы помним из первой статьи, после этой операции в переменной «$x» остается только расширение файла. Затем bash сравнивает это расширение с вариантами стоящими слева от одинарных скобок «)«. Если совпадение найдено, выполняется соответствующее действие. Если совпадения не найдено, никаких действий не выполняется, но в данном конкретном коде совпадение будет всегда, потому что в последней строке стоит шаблон «*«, совпадающий с любой последовательностью символов.

Функции и пространство имен

В bash вы можете определять свои функции, как и в других языках программирования (C, Pascal…).

Эти функции могут принимать аргументы, используя механизм очень похожий на механизм работы с аргументами командной строки. Вот пример определения простой функции:

Эта функция может быть переписана с использованием конструкции «case«. Сможете ли вы проделать это самостоятельно?

Выше мы определили функцию с именем «tarview», которая принимает один аргумент — имя тарбола. Эта функция определяет вид тарбола (без сжатия, сжатый gzip-ом или bzip2) по расширению, затем печатает этот тип и показывает содержимое архива. Если формат определить не удалось, выводится соответствующее сообщение. Вот пример вызова функции:

Как вы видите, обращение к аргументам внутри функции происходит по тем же именам как и к аргументам командной строки внутри скрипта. Переменная «$#» содержит количество переданных функции аргументов. Единственное что остается по-прежнему — переменная «$0«. Она содержит название скрипта при вызове функции из скрипта или строку «bash» при вызове функции напрямую из командной строки.

Вызвать функцию из командной строки можно следующим образом: сохраняем код функции в файл (например с названием «myfunc.txt») а затем даем следующую команду:

или что тоже самое

Эти команды строка за строкой исполняют инструкции написанные в файле в текущей командной оболочке. (Можно так же напечатать код функции строка за строкой в командной строке, но первый способ намного удобнее). После этого можем вызывать нашу функцию прямо из командной строки:

Замечание: любая функция может быть записана в файл ~/.bashrc или ~/.bash_profile, тогда вы сможете вызывать ее из командной строки в любое время при следующем логине.

Пространство имен

Часто возникает потребность создать переменную окружения внутри функции.

В большинстве компилируемых языков (например Си), когда вы создаете переменную внутри функции, она попадает в отдельное пространство имен этой функции. Например, если вы напишите функцию «my function» на C и внутри этой функции создадите переменную «x», то она никак не повлияет на переменную с тем же именем «x», созданную вне функции «myfunction».

Но в bash все по-другому. В bash, когда вы создаете переменную внутри функции, она попадает в общее пространство имен. Это значит, что она может перезаписать значение глобальной переменной с таким же именем и продолжит свое существование даже после завершения исполнения функции:

Результатом исполнения этого кода будет строка «ne two three three«, показывающая что переменная «myvar», созданная внутри функции перезаписала значение глобальной переменной «myvar» и что последнее значение итератора «x» равное «three» продолжило существование даже после завершения функции.

В этом простом примере ошибку легко заметить и устранить, переименовав переменные внутри функции. Но есть гораздо более правильное решение этой проблемы: при создании переменной можно явно указать что она является локальной при помощи инструкции «local«. Созданная таким способом внутри функции переменная будет отнесена к локальному пространству имен этой функции и не сможет никак повлиять на глобальную переменную с таким же именем. Следующий пример демонстрирует возможность создания локальной переменной:

Результатом выполнения этого кода будет строка «hello» — значение глобальной переменной «myvar» (на которую никак не повлияла локальная переменная «myvar», созданная внутри функции), а локальная переменная «x» перестает существовать после завершения функции.

Единственное условие при котором вы не должны использовать локальные переменные внутри функций — если хотите изменить значение глобальной переменной.

Подведение итогов

Вот и все. Теперь вы имеете представление о программировании в bash и можете писать свои скрипты. За более подробной информацией обращайтесь к справке man bash или к руководству Advanced Bash-Scripting Guide

Смотри также


Оригинал статьи— Bash by example, Part 2 (eng)

Как представить несколько условий в инструкции shell if?

Изучаем BASH (Основы)

Автор: Admin

Дата:2012-12-10

Учимся писать сценарии

В большинстве своем весь Linux состоит из скриптов, поэтому просто необходимо знать этот язык.
По своей сути это всего лишь набор команд Linux, объединенных при помощи разных конструкций в грамотно и хорошо продуманный код.

Давайте создадим наш первый сценарий.
Для этого просто откроем текстовый редактор и наполним файл следующим:

vim bash1.sh

#!/bin/bash
who; date

Здесь все просто.
По своей сути знак диеза (#), в большинстве случаев, рассматривается как начало комментария, однако здесь начиная с первой строки он говорит нам, что должен использоваться интерпретатор bash.

Дальше мы просто выполняем две команды подряд.
Здесь стоит обратить внимание на две особенности:

1) Необходимо дать права на выполнение

chmod u+x bash1.sh

2) echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/game

И переместить этот файлик в одну из директорий, если конечно вам нужно обращаться к нему просто по имени, а не по полному месту расположения.

Здесь мы рассмотрели то как создается сценарий, дальше нужно уяснить несколько вещей.

Всегда при написании сценариев мы будем обращаться с переменными, перенаправлять ввод и вывод, работать с каналами и выполнять математические вычисления.


Переменные

Для определения новой переменной достаточно сказать:

vim bash2.sh

#!/bin/bash
F=Ivan
I=Ivanov
O=Ivanich
#Выводится с помощью:
echo «FIO $F $I $O»

Результат

sh bash2.sh
FIO Ivan Ivanov Ivanich

Посмотреть переменные;
# set

BASH=/bin/bash
HISTFILE=/root/.bash_history
HISTFILESIZE=500
HISTSIZE=500
HOME=/root
SSH_CLIENT=’192.168.200.3 9382 22′
SSH_CONNECTION=’192.168.200.3 9382 192.168.200.252 22′

Существует еще один очень интересный и полезный способ задания переменной при помощи `   `

#!/bin/bash
day=`date +%y%m%d`
# В дальнейшем переменную $day можно вставить в скрипт, например бэкапа

rsync -avz /root/data /root/backup.$day

В результате выполнения такого скрипта появится бэкап с определением даты создания бэкапа.

Перенаправление ввода и вывода.

> Перенаправление в файл с полным затираем содержимого файла
>> Перенаправление с добавлением в файл, к концу уже имеющегося содержимого.
ls -al / > 123
А команда:
ls -al /home >> 123
Выведет список всех файлов из корня и затем добавит после этого содержимое каталога Home
такое перенаправление называется перенаправление вывода
Перенаправление ввода — содержимое перенаправляется в команду.
sort < sort.txt
Команды сорт производит сортировку по алфавиту в результате чего, хаотично наполненный файл sort.txt  после перенаправления в программу sort будет отсортирован по алфавиту
sort < sort.txt | more — а построение в канал отобразит отсортированные данные постранично
sort < sort.txt | grep s | more — отсортирует и выведет все со знаком «S»

Каналы

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

 cat /var/log/maillog | grep blocked | more

1) cat — выводит на экран весь лог файл
2) дальше этот лог файл передается на обработку команде grep которая выводит только с Blocked, но так как сообщений с этим статусом много необходимо передать ее команде more
3) more — необходима для постраничного просмотра данных

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

Математические вычисления

Математические вычисления в Linux  легче всего выполнять при помощи команды bc
При этом неследует задать количество знаков после плаваюшей запятой при помощи scale

#!/bin/bash
var1=45
var2=22
var3=`echo «scale=3; $var1/$var2» | bc`
echo $var3

Далее >>> Изучаем BASH (Интсрукции)

Количество просмотров: 6472

© Plutonit.ru — Администрирование, настройка Linux и Windows 2009 — 2018

Bash в примерах. Часть первая.

Основы программирования в bash

Введение

Вы, должно быть, пока не представляете зачем нужно учиться программированию в bash. Вот несколько причин:

Bash уже есть у вас в системе

Если вы проверите, то скорее всего обнаружите, что bash уже запущен у вас в системе. Даже если вы используете другой shell в качестве командного интерпретатора, bash наверняка установлен, потому что он является стандартной командной оболочкой в линуксе. Так как bash уже запущен, выполнение скриптов написанных на bash-е является эффективным, потому что они разделяют часть оперативной памяти с уже запущенным процессом bash. Да и зачем загружать еще один интерпретатор, если у вас уже есть bash, который справляется со своей работой и делает это хорошо?

Вы уже используете его

Но bash не просто запущен в вашей системе, вы еще ежедневно взаимодействуете с ним. Он всегда рядом, так что есть смысл научиться управляться с ним чтобы полноценно использовать все его возможности. После этого ваше общение с линуксом станет намного веселее и продуктивнее. Но почему вы должны учиться программировать? Все просто: вы уже мыслите в терминах исполнения программ, копирования файлов и перенаправления вывода программ. Не должны ли вы теперь изучить язык, который позволит вам строить из этих простых элементов мощные и экономящие ваше время конструкции с использованием которых вы уже знакомы? Командная оболочка открывает перед вами весь потенциал UNIX. А bash это командная оболочка линукс. Он связывает вас с компьютером. Изучив bash, вы автоматически увеличите свою производительность использования UNIX или Linux — все настолько просто.

Перед началом

Неправильный подход к изучению языка bash может сбить вас с толку. Многие новички вводят команду man bash чтобы прочитать страницу со справкой, которая содержит только краткое техническое описание функционала командной оболочки. Другие вызывают info bash (чтобы посмотреть документацию в формате info), но получают или ту же страницу мануала или немногим более удобный для пользователя материал.

Новички могут быть немного разочарованы, узнав что стандартная справка не может предоставить всей информации и предназначена для пользователей уже знакомых с основами программирования на языке shell. В мануале много замечательно организованной технической информации, но для новичков ее польза невелика.

Эта серия статей поможет вам освоиться в командной строке. В этом пособии описано как использовать основные синтаксические конструкции языка shell для написания своих скриптов. Я постараюсь объяснить все простым языком, чтобы вы не только поняли как это все работает, но и разобрались как это использовать. Прочитав эту серию статей, вы научитесь писать свои собственные скрипты и будете комфортно себя чувствовать в командной строке. После этого вы сможете пополнять свои знания читая (и понимая!) стандартную документацию по bash. Давайте начнем.

Переменные окружения

В bash как и практически во всех остальных командных оболочках пользователь может создавать и определять свои переменные окружения, которые хранятся как текстовые (ASCII) строки. Одно из самых полезных свойств переменных окружения заключается в том, что они являются стандартной частью модели процессов в UNIX. Это значит, что переменные окружения могут использовать не только скрипты командной оболочки, но и компилированные программы. Когда мы экспортируем переменную окружения в bash, любая программа запущенная нами получает к ней доступ. Хорошим примером служит команда vipw, которая позволяет руту редактировать файл с паролями пользователей (/etc/passwd). Установив переменную окружения EDITOR в значение своего любимого текстового редактора, вы можете указать vipw использовать его, а не редактор по умолчанию.

Переменную в bash-е можно определить следующим способом:

Эта команда создает переменную с именем «myvar» которая содержит строку «Это моя переменная окружения!». Следует заметить что: Во-первых, рядом со знаком «=» не должно быть пробелов; (попробуйте и вы увидите, что на команду с пробелами интерпретатор выдает ошибку). Во-вторых, если значение нашей переменной содержит пробелы или знаки табуляции, нужно заключить его в кавычки.

Замечание: За подробной информацией об использовании кавычек в bash обратитесь к разделу «QUOTING» на странице man bash. Существование специальных последовательностей символов, которые интерпретатор заменяет другими значениями, делает объяснение работы со строками в bash слишком сложным. Поэтому мы расскажем только о наиболее часто используемых способах применения кавычек.

В-третьих, обычно можно использовать двойные кавычки вместо одинарных, но именно в этом примере использование двойных кавычек вызовет ошибку интерпретатора, так как значение нашей переменной содержит один из тех специальных символов (о которых сказано в замечании выше) — «!«, но внутри одинарных кавычек никакие специальные символы не работают. Символ «!» в bash отвечает за так называемую «HISTORY EXPANSION» — работу с файлом истории командной строки (подробности см. в мануале). На смотря на то, что функция работы с историей команд при помощи «!» бывает очень полезной, именно сейчас мы хотим видеть его просто как восклицательный знак.

Давайте посмотрим как можно прочитать значение нашей переменной:

Ставя перед именем переменной знак $, мы сообщаем интерпретатору, что нужно заменить ее значением. Это называется подстановкой переменной (variable substitution/expansion).

Нужно заметить, что имена переменных в bash чувствительны к регистру.

Например, myvar и Myvar — это имена разных переменных.

Но что будет, если мы попробуем сделать так:

Мы хотели вывести на экран надпись ‘fooЭто моя переменная окружения!bar‘, но ничего не получилось. Что же произошло? Интерпретатор не смог определить значение какой именно переменной нужно подставить ($m, $my, $myvar, $myvarbar и т.д.) В таких неоднозначных случаях можно явно указать bash на имя переменной:

Как вы видите, заключив имя нужной переменной в фигурные скобки, мы явно указали интерпретатору где находится переменная, а где простой текст. Выражение $myvar быстрее напечатать и оно работает в большинстве случаев, но ${myvar} будет работать всегда корректно. Оба этих выражения указывают на одну переменную, но вы должны использовать второе (с фигурными скобками), если имя переменной не отделено от окружающего текста пробелами или знаками табуляции.

Вернемся к упомянутой нами возможности экспортировать переменные. Экспортированная переменная автоматически становится доступна для любого скрипта или программы, запущенной после экспортирования. Shell-скрипт может прочитать значение переменной при помощи встроенных в shell средств работы с переменными окружения, а программы на C — используя функцию getenv(). Вот небольшой пример кода на языке C, который вы можете напечатать и скомпилировать. Он поможет взглянуть на переменные окружения со стороны языка C:

Сохраните этот код в файл myenv.c, а затем скомпилируйте:

После этого в ващей рабочей директории появится исполняемый файл ‘myenv‘. Запустите его, и он выведет вам значение переменной ‘EDITOR‘ (если оно присвоено). Вот что получилось у меня:

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

Так тоже не работает. Мы ожидали что программа напечатает «mousepad», но результат не изменился. Это произошло потому что мы забыли экспортировать переменную ‘EDITOR‘. В этот раз должно сработать:

Итак, мы на примере убедились, что сторонний процесс (в нашем случае программа на C) не может получить доступ к переменной окружения до тех пор пока она не экспортирована. Кроме того, вы можете определить переменную и экспортировать ее одной командой:

Эта команда выполняет то же действие, что и двухшаговая версия (присвоение значения и экспорт). Наступило подходящее время показать как сбросить значение переменной окружения (другими словами — удалить переменную) при помощи ‘unset‘:

Как распарсить строку?

Распарсить строку — значит разделить ее на более короткие составляющие. Это одна из частых операций, встречающихся при написании shell-скриптов. Иногда скрипту нужно определить имя конкретного файла или директории, зная полный (абсолютный) путь к нему. На bash это можно сделать всего одной командой:

basename‘ — очень удобная утилита для расщепления строк на составляющие. Вторая команда — ‘dirname‘ — возвращает другую часть строки (путь к директории где находится файл):

Замечание: команды ‘basename‘ и ‘dirname‘ не определяют наличие файла или директории в файловой системе, а работают только со строками.

Подстановка команд

Очень полезно знать как присвоить переменной результат выполнения какой-либо команды. Сделать это довольно просто:

То что мы сделали называется подстановка команд. В первой строке примера мы просто заключили команду в конструкцию $( ).

Заметим, что тоже самое можно сделать применив вместо конструкции $( ) обратные кавычки « (клавиша клавиатуры сразу над клавишей Tab):

В баше, как мы видим, можно сделать одно действие несколькими разными способами. Используя подстановку команд, мы можем поместить любую команду в обратные кавычки или в конструкцию $( ) и присвоить ее вывод переменной. Очень полезная вещь! Вот пример как использовать подстановку серии команд соединенных через пайп:

Стоит заметить, что использование конструкции $( ) предпочтительней чем обратных кавычек в shell-скриптах, т.к. она более универсальна по отношению к разным командным интерпретаторам, ее легче набирать и читать и ее можно использовать во вложенных конструкциях:

Расщепление строк для профессионалов

basename‘ и ‘dirname‘ замечательные утилиты, но бывают случаи, когда нужно произвести более сложные операции над строками чем манипуляции с путями. Для более эффективной работы со строками можно использовать встроенные средства подстановки значений переменных bash. Ранее мы уже использовали подстановку переменных, которая выглядела так: ${myvar}. Но в bash есть и встроенные средства манипуляции со строками. Посмотрим на следующий пример:

Что же означает конструкция ${MYVAR##*fo} из предыдущего примера? Мы написали внутри ${ } имя переменной, затем два знака хэша (или диеза, кому как привычней) и шаблон («*fo»). Bash взял нашу переменную ‘MYVAR’, нашел наибольшую по длине подстроку строки ‘foodforthought.jpg’ (начиная от начала строки) которая совпала с шаблоном «*fo» и удалил ее. С первого раза в этих тонкостях сложно разобраться. Для того чтобы понять как работает конструкция ##, давайте рассмотрим пошагово как bash ищет совпадение подстроки с шаблоном. Начинаем поиск подстроки совпадающей с шаблоном «*fo» с начала строки «foodforthought.jpg». Вот список всех таких подстрок:

После проверки всех этих вариантов, найдено две строки попадающие под шаблон. Bash выбирает самую длинную из них, а затем удаляет эту подстроку и возвращает результат.

Вторая форма подстановки переменной показанная в примере отличается от первой только наличием одного знака хэша (#), а не двух. И bash выполняет те же действия, за исключением того, что удаляет не самую длинную а самую короткую из совпавших с шаблоном подстрок. Как видно, после удаления самой короткой подстроки совпавшей с шаблоном (fo) у нас остается строка «odforthought.jpg».

Это может показаться очень запутанным, поэтому я покажу как можно быстро запомнить эту фичу bash. Когда мы ищем самое длинное совпадение, то используем два хэша (##), т.к. «##» длиннее чем «#». А когда ищем самое короткое совпадение, используем #. Видите, не так уж и сложно! Постойте, а как же запомнить, что поиск начинается от начала строки? Очень просто! Заметим, что в английской раскладке клавиатуры сочетание Shift–4 дает нам знак $ используемый в bash для подстановки значения переменной. Сразу перед знаком $ на клавиатуре находится # (как бы вначале) и таким образом «#» удаляет символы от начала строки. Вы захотите узнать, как удалить последовательность символов от конца строки. Как можно догадаться, это делается при помощи знака (%), находящегося на клавиатуре сразу после «$». Вот небольшой пример удаления окончания строки:

Как вы видите, одинарный и двойной знаки процента (% и %%) работают также как «#» и «##», но удаляют подстроку совпавшую с шаблоном от конца строки. Запомните, что можно не использовать знак «*», если вы хотите удалить какое-то конкретное окончание строки.

В этом примере нет разницы использовать % или %%, т.к. есть только одно совпадение. И не забывайте при выборе «#» или «%» смотреть на 3,4 и 5 клавиши клавиатуры.

Мы можем использовать еще одну форму подстановки значения переменной для выделения подстроки по заданной длине и позиции начала:

Эта форма очень удобна.

Проверка условий в Bash

Просто укажите разделяя двоеточиями позицию начала подстроки — первое число и длину подстроки — второе число.

Применение расщепления строк

Разделению строк научились, давайте теперь напишем небольшой shell-скрипт. Наш скрипт будет принимать один аргумент — имя файла и если этот файл имеет расширение .tar, скрипт будет сообщать что это тарбол. (На самом деле определять тип файла по расширению не совсем корректно. Для этих целей существует команда file. Пример только для демонстрации.) Вот этот скрипт:

Первая строка обязательно должна присутствовать в каждом скрипте. Она показывает путь к интерпретатору, который будет выполнять скрипт. Ее синтаксис, как видно из примера — «#!<путь к интерпретатору>».

Сохраните текст скрипта из примера в файл mytar.sh, затем измените права доступа к нему ‘chmod 755 mytar.sh‘ (это сделает файл исполняемым). И, наконец, запустите скрипт с аргументом в виде имени файла, как показано в следующем примере:

Хорошо, вроде работает, но не очень функционален. Перед тем как усовершенствовать наш скрипт, рассмотрим конструкцию if, использованную в нем. В квадратных скобках сравниваются две строки («=» — это оператор сравнения в bash). Результат сравнения — булевое выражение ‘false’ или ‘true’ (правда или ложь). Но давайте посмотрим какие именно строки сравниваются. Справа все понятно — строка «tar». Слева стоит разобранное нами выше выражение, удаляющее начало строки в переменной $1 по шаблону «*.» (вся строка до последней точки, т.к. используются два хэша ##). После этой операции подстановки остается только часть строки после последней точки — расширение другими словами.

Если в переменной $1 содержится имя файла с расширением «tar», то результатом сравнения строк будет булевое true.

Вам наверное интересно, почему при проверке условия мы использовали переменную «$1». Все очень просто: переменная $1 содержит в себе первый аргумент переданный скрипту ($2 — второй аргумент и так далее). С этой функцией разобрались, рассмотрим теперь подробнее конструкцию условного выбора «if«.

Конструкция if

Как и во многих языках программирования, в bash есть условные конструкции. Они имеют формат, описанный ниже. Будьте внимательны: слова «if» и «then» должны находится на разных строках. Старайтесь выравнивать горизонтально всю конструкцию, включая заключительный «fi» и все «else». Это делает код намного удобнее для чтения и отладки. В дополнении к простой форме «if,else» есть еще несколько других форм условных конструкций:

В приведенном выше примере ‘действие’ выполняется только если ‘условие’ верно, в противном случае скрипт продолжает выполнение инструкций со строки идущей за «fi».

А эта конструкция последовательно проверяет условия и если они верны, то исполняет соответствующее действие.

Если ни одно из условий не верно, то выполняется ‘действие_x’ стоящее после ‘else’ (если оно есть). Потом продолжается исполнение команд идущих за этой конструкцией «if,then,else», если таковые есть.

В следующей части

В этой статье мы рассмотрели базовую функциональность bash. Пришло время немного ускориться и начать писать свои собственные shell-скрипты. В следующей части пособия я расскажу о функциях, циклах, пространстве имен и о других важных вещах. После этого мы будем готовы писать относительно сложные скрипты. До встречи!

Смотри также


Оригинал статьи— Bash by example, Part 1 (eng)

Далее перечислены символы и синтаксические конструкции, имеющее особое значение в bash. Для ввода спецсимволов как они есть используют кавычки или спецсимвол \ отменяющий специальное значение следующего символа

\ Экранирование. Отменяет специальное значение следующего символа
\\ Символ "\"

# Комментарий, не работает в кавычках и в некоторых подстановках переменных и преобразовании основания чисел
echo "Это #не комментарий"
echo 'Это # не комментарий’
echo Это \# не комментарий
echo Это # Вот комментарий.
echo ${PATH#*:} #Специальная переменная
echo $(( 2#101011 )) #Преобразование системы счисления в арифметической подстановке.

>, >> — перенаправление стандартного вывода программы в файл
< — перенаправление стандартного ввода программы из файла
<<TERM перенаправление стандартного ввода программы из текста текущего скрипта со следующей строки до строки, состоящей из слова TERM.
|- перенаправление стандартного вывода программы на стандартный ввод другой программы

; Разделитель команд в строке
echo hello; echo there

;; Разделитель альтернатив в операторе case
case "$VARiable" in
abc) echo "$VARiable = abc" ;;
xyz) echo "$VARiable = xyz" ;;
esac

. Аналог команды source (#include в С++). Выполняет скрипт в текущем интерпретаторе.
. myconf

".." Двойные кавычки, отменяют действие спецсимволов кроме $ `..` и \

'…' Апострофы, отменяют действие всех спецсимволов в том числе и \, по этому нельзя включить апостроф в строку ограниченную апострофами

: Нулевая команда, всегда возвращает нулевой код ответа.

4 Bash If Statement Examples ( If then fi, If then else fi, If elif else fi, Nested if )

В сочетании с перенаправлением ">" создает файл, или обнуляет существующий. В сочетании с перенаправлением ">>" создает файл, или изменяет время модификации существующего
:> data.xxx # File “data.xxx” now empty.
(можно и без двоеточия)

Шаблоны в именах файлов. Если подходящие имена находятся, то они подставляются в командную строку как отдельные аргументы (возможно с пробелами внутри). Если имена не находятся, то шаблон остается как есть.

* Шаблон заменяющий любую последовательность символов
? Шаблон заменяющий ровно один символ
[xyz] Шаблон заменяющий один из перечисленных символов
{xxx,yyy,zzz,…} Подстановка одного из вариантов в шаблон. В скобках не должно быть неэкранированных пробелов
grep Linux file*.{txt,htm*} # Ищет слово “Linux” в файлах вида “fileA.txt”, “file2.txt”, “fileR.html”, “file-87.htm”, etc.

$ Подстановка значения переменной, арифметического выражения или стандартного вывода программы. Если значение содержит пробелы, то при подстановке оно разбивается на отдельные аргументы.
$A содержимое переменной A
$$ PID процесса
$? Код возврата из последней выполненной программы или функции, а также код возврата самого скрипта
$((2*2)) подстановка результата вычисления арифметического выражения
$(cmd) подстановка стандартного вывода программы
`…` тоже, что и $(…) – подстановка стандартного вывода программы

Пример: A=EE; echo $A $(echo QQ) $((7+5))
Результат: EE QQ 12
Ошибка: $A=ZZ
Результат: bash: EE=ZZ: command not found

(…) Группировка команд
(A=hello; echo $A)
Для выполнения группы в скобках запускается новый интерпретатор
A=123
(A=321)
echo A = $A # A = 123
# "A" внутри скобок – локальная переменная.

(…) Создание массива ( только в bash версии > 2)
Array=(element1 element2 element3)

[] Элемент массива ( только в bash версии > 2)
Array[1]=slot_1
echo ${Array[1]}

{1..10} — подстановка чисел от 1 до 10
{c..n} — подстановка символов от "c" до "n"

{…} Создание безымянной функции, удобно для перенаправления ввода/вывода нескольких команд в один файл. В отличие от настоящей функции видимости переменных не изменяется.
PACK=mysql
{
echo
echo "Archive Listing:"
rpm -qpl ${PACK} # Список фалов в пакете rpm
echo
rpm -i —test ${PACK} # Проверка, установлен ли пакет.
} > "${PACK}.txt" #И весь вывод в один файл.

[…] Встроенная функция test для вычисления логических выражений

((…)) Арифметическая подстановка, вычисляет арифметическое выражение в стиле языка Си внутри скобок

& — запуск программы в фоновом режиме
bash$ sleep 10 &
[1] 850
[1]+ Done sleep 10

Shell — это один из командных интерпретаторов, поставляемых вместе с ОС unix.

bash конструкция if синтаксис

Программа на языке Shell называется скриптом. Shell скрпитам указывают расширение *.sh и работают они Unix системах. Если вам надо запустить shell скрипт в windows, то можно установить подсистему Linux Ubuntu или установить отдельно интерпретатор Shell для windows.

Как запустить sh скрипт из командной строки?

Допустим у вас есть скрипт hello.sh состоящий из одной команды.

Чтобы его запустить скрипт, надо зайти в каталог, где расположен скрипт, набрать название интерпретатора sh и первым параметров указать ваш файл hello.sh.

Чтобы каждый раз не указывать интерпретатор в терминале, можно сделать скрипт исполняемым. Для этого необходимо:

  • Указать интерпретатор внутри файла.
    На первой строчке после #! прописывам путь к bash-интерпретатору, по-умолчанию это /bin/bash (посмотреть можно командой whereis bash). Содержмиое скрипта hello.sh получается таким:
  • Сделать наш файл исполняемым. Для этого используется команда chmod +x и имя файла скрипта:

Теперь можно запускать:

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *