Linux bash скрипты функции

Глава 22. Функции

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

Вторая форма записи ближе к сердцу C-программистам (она же более переносимая).

Как и в языке C, скобка, открывающая тело функции, может помещаться на следующей строке.

Вызов функции осуществляется простым указанием ее имени в тексте сценария.

Пример 22-1. Простая функция

Функция должна быть объявлена раньше, чем ее можно будет использовать. К сожалению, в Bash нет возможности «опережающего объявления» функции, как например в C.

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

Объявление функции может размещаться в самых неожиданных местах.

22.1. Сложные функции и сложности с функциями

Функции могут принимать входные аргументы и возвращать код завершения.

Доступ к входным аргументам, в функциях, производится посредством позиционных параметров, т.е. $1, $2 и так далее.

Пример 22-2. Функция с аргументами

Команда shift вполне применима и к аргументам функций (см. Пример 33-10).

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

Exit и Return

Функции возвращают значение в виде кода завершения. Код завершения может быть задан явно, с помощью команды return, в противном случае будет возвращен код завершения последней команды в функции ( 0 — в случае успеха, иначе — ненулевой код ошибки). Код завершения в сценарии может быть получен через переменную $?.

Завершает исполнение функции. Команда return [2] может иметь необязательный аргумент типа integer , который возвращается в вызывающий сценарий как «код завершения» функции, это значение так же записывается в переменную $?.

Пример 22-3. Наибольшее из двух чисел

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

Пример 22-4. Преобразование чисел в римскую форму записи

Наибольшее положительное целое число, которое может вернуть функция — 255. Команда return очень тесно связана с понятием код завершения, что объясняет это специфическое ограничение. К счастью существуют различные способы преодоления этого ограничения.

Пример 22-5. Проверка возможности возврата функциями больших значений

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

Еще один способ — использовать глобальные переменные для хранения «возвращаемого значения» .

Пример 22-6. Сравнение двух больших целых чисел

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

Перенаправление

Перенаправление ввода для функций

Функции — суть есть блок кода, а это означает, что устройство stdin для функций может быть переопределено (перенаправление stdin) (как в Пример 3-1).

Пример 22-7. Настоящее имя пользователя

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

Примечания

Механизм косвенных ссылок на переменные (см. Пример 34-2) слишком неудобен для передачи аргументов по ссылке.

Команда return — это встроенная команда Bash.

Источник

Bash Функции

Bash Functions

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

Функция Bash — это, по сути, набор команд, которые можно вызывать множество раз. Цель функции — помочь вам сделать ваши bash-скрипты более читабельными и избежать повторного написания одного и того же кода. По сравнению с большинством языков программирования, функции Bash несколько ограничены.

Определение функций Bash

Синтаксис объявления функции bash прост. Функции могут быть объявлены в двух разных форматах:

Первый формат начинается с имени функции, за которым следуют скобки. Это предпочтительный и более используемый формат.

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

Несколько моментов, которые следует отметить:

  • Команды между фигурными скобками ( <> ) называются телом функции. Фигурные скобки должны быть отделены от тела пробелами или переводами строки.
  • Определение функции не выполняет ее. Чтобы вызвать функцию bash, просто используйте имя функции. Команды между фигурными скобками выполняются всякий раз, когда функция вызывается в сценарии оболочки.
  • Определение функции должно быть помещено перед любыми вызовами функции.
  • При использовании однострочных «уплотненных» функций точка с запятой ; должна следовать за последней командой в функции.
  • Всегда старайтесь, чтобы имена ваших функций были описательными.

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

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

  • В строке 3 мы определяем функцию, присваивая ей имя. Фигурная скобка < отмечает начало тела функции.
  • Линия 4 — это тело функции. Тело функции может содержать несколько команд, операторов и объявлений переменных.
  • Линия 5 , закрывающая фигурная скобка > , определяет конец hello_world функции.
  • В строке 7 мы выполняем функцию. Вы можете выполнять функцию столько раз, сколько вам нужно.

Если вы запустите скрипт, он напечатает hello, world .

Область действия переменных

Глобальные переменные — это переменные, к которым можно получить доступ из любого места в скрипте независимо от области видимости. В Bash все переменные по умолчанию определены как глобальные, даже если они объявлены внутри функции.

Локальные переменные могут быть объявлены в теле функции с local ключевым словом и могут использоваться только внутри этой функции. Вы можете иметь локальные переменные с одинаковыми именами в разных функциях.

Чтобы лучше проиллюстрировать, как работает область видимости переменных в Bash, давайте рассмотрим этот пример:

Сценарий начинается с определения двух глобальных переменных var1 и var2 . Затем есть функция, которая устанавливает локальную переменную var1 и изменяет глобальную переменную var2 .

Если вы запустите скрипт, вы должны увидеть следующий вывод:

Из приведенного выше вывода можно сделать вывод, что:

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

Возвращаемые значения

В отличие от функций в «реальных» языках программирования, функции Bash не позволяют вам возвращать значение при вызове. Когда функция bash завершает свою работу, ее возвращаемое значение является состоянием последнего оператора, выполненного в функции, 0 для успеха и ненулевого десятичного числа в диапазоне 1 — 255 для отказа.

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

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

Другой, лучший вариант для возврата значения из функции отправить значение с stdout помощью эха или , printf как показано ниже:

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

Передача аргументов в функции Bash

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

  • Передаваемые параметры $1 , $2 , $3 . $n , соответствующее положению параметра после имени функции.
  • $0 Переменная зарезервирована для имени функции.
  • $# Переменная содержит число позиционных параметров / аргументов , передаваемых функции.
  • $* И $@ переменные содержат все позиционные параметры / аргументы , переданные функции.
    • При двойных кавычках «$*» раскрывается в одну строку, разделенную пробелом (первый символ IFS) — «$1 $2 $n» .
    • При двойных кавычках «$@» расширяется до отдельных строк — «$1» «$2» «$n» .
    • Когда не двойные кавычки, $* а $@ одинаковые.

Вывод

Функция Bash — это блок многократно используемого кода, предназначенный для выполнения определенной операции. После определения функция может вызываться несколько раз в скрипте.

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

Источник

Bash-скрипты: начало

Сегодня поговорим о bash-скриптах. Это — сценарии командной строки, написанные для оболочки bash. Существуют и другие оболочки, например — zsh, tcsh, ksh, но мы сосредоточимся на bash. Этот материал предназначен для всех желающих, единственное условие — умение работать в командной строке Linux.

Сценарии командной строки — это наборы тех же самых команд, которые можно вводить с клавиатуры, собранные в файлы и объединённые некоей общей целью. При этом результаты работы команд могут представлять либо самостоятельную ценность, либо служить входными данными для других команд. Сценарии — это мощный способ автоматизации часто выполняемых действий.

Итак, если говорить о командной строке, она позволяет выполнить несколько команд за один раз, введя их через точку с запятой:

На самом деле, если вы опробовали это в своём терминале, ваш первый bash-скрипт, в котором задействованы две команды, уже написан. Работает он так. Сначала команда pwd выводит на экран сведения о текущей рабочей директории, потом команда whoami показывает данные о пользователе, под которым вы вошли в систему.

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

Командная строка — отличный инструмент, но команды в неё приходится вводить каждый раз, когда в них возникает необходимость. Что если записать набор команд в файл и просто вызывать этот файл для их выполнения? Собственно говоря, тот файл, о котором мы говорим, и называется сценарием командной строки.

Как устроены bash-скрипты

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

В других строках этого файла символ решётки используется для обозначения комментариев, которые оболочка не обрабатывает. Однако, первая строка — это особый случай, здесь решётка, за которой следует восклицательный знак (эту последовательность называют шебанг) и путь к bash , указывают системе на то, что сценарий создан именно для bash .

Команды оболочки отделяются знаком перевода строки, комментарии выделяют знаком решётки. Вот как это выглядит:

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

Установка разрешений для файла сценария

Сохраните файл, дав ему имя myscript , и работа по созданию bash-скрипта почти закончена. Сейчас осталось лишь сделать этот файл исполняемым, иначе, попытавшись его запустить, вы столкнётесь с ошибкой Permission denied .

Попытка запуска файла сценария с неправильно настроенными разрешениями

Сделаем файл исполняемым:

Теперь попытаемся его выполнить:

После настройки разрешений всё работает как надо.

Успешный запуск bash-скрипта

Вывод сообщений

Для вывода текста в консоль Linux применяется команда echo . Воспользуемся знанием этого факта и отредактируем наш скрипт, добавив пояснения к данным, которые выводят уже имеющиеся в нём команды:

Вот что получится после запуска обновлённого скрипта.

Вывод сообщений из скрипта

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

Использование переменных

Переменные позволяют хранить в файле сценария информацию, например — результаты работы команд для использования их другими командами.

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

Существуют два типа переменных, которые можно использовать в bash-скриптах:

  • Переменные среды
  • Пользовательские переменные

Переменные среды

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

Обратите внимание на то, что мы можем использовать системную переменную $HOME в двойных кавычках, это не помешает системе её распознать. Вот что получится, если выполнить вышеприведённый сценарий.

Использование переменной среды в сценарии

А что если надо вывести на экран значок доллара? Попробуем так:

Система обнаружит знак доллара в строке, ограниченной кавычками, и решит, что мы сослались на переменную. Скрипт попытается вывести на экран значение неопределённой переменной $1 . Это не то, что нам нужно. Что делать?

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

Теперь сценарий выведет именно то, что ожидается.

Использование управляющей последовательности для вывода знака доллара

Пользовательские переменные

В дополнение к переменным среды, bash-скрипты позволяют задавать и использовать в сценарии собственные переменные. Подобные переменные хранят значение до тех пор, пока не завершится выполнение сценария.

Как и в случае с системными переменными, к пользовательским переменным можно обращаться, используя знак доллара:

Вот что получится после запуска такого сценария.

Пользовательские переменные в сценарии

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

Одна из самых полезных возможностей bash-скриптов — это возможность извлекать информацию из вывода команд и назначать её переменным, что позволяет использовать эту информацию где угодно в файле сценария.

Сделать это можно двумя способами.

  • С помощью значка обратного апострофа «`»
  • С помощью конструкции $()

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

При втором подходе то же самое записывают так:

А скрипт, в итоге, может выглядеть так:

В ходе его работы вывод команды pwd будет сохранён в переменной mydir , содержимое которой, с помощью команды echo , попадёт в консоль.

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

Математические операции

Для выполнения математических операций в файле скрипта можно использовать конструкцию вида $((a+b)) :

Математические операции в сценарии

Управляющая конструкция if-then

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

А вот рабочий пример:

В данном случае, если выполнение команды pwd завершится успешно, в консоль будет выведен текст «it works».

Воспользуемся имеющимися у нас знаниями и напишем более сложный сценарий. Скажем, надо найти некоего пользователя в /etc/passwd , и если найти его удалось, сообщить о том, что он существует.

Вот что получается после запуска этого скрипта.

Здесь мы воспользовались командой grep для поиска пользователя в файле /etc/passwd . Если команда grep вам незнакома, её описание можно найти здесь.

В этом примере, если пользователь найден, скрипт выведет соответствующее сообщение. А если найти пользователя не удалось? В данном случае скрипт просто завершит выполнение, ничего нам не сообщив. Хотелось бы, чтобы он сказал нам и об этом, поэтому усовершенствуем код.

Управляющая конструкция if-then-else

Для того, чтобы программа смогла сообщить и о результатах успешного поиска, и о неудаче, воспользуемся конструкцией if-then-else . Вот как она устроена:

Если первая команда возвратит ноль, что означает её успешное выполнение, условие окажется истинным и выполнение не пойдёт по ветке else . В противном случае, если будет возвращено что-то, отличающееся от нуля, что будет означать неудачу, или ложный результат, будут выполнены команды, расположенные после else .

Напишем такой скрипт:

Его исполнение пошло по ветке else .

Запуск скрипта с конструкцией if-then-else

Ну что же, продолжаем двигаться дальше и зададимся вопросом о более сложных условиях. Что если надо проверить не одно условие, а несколько? Например, если нужный пользователь найден, надо вывести одно сообщение, если выполняется ещё какое-то условие — ещё одно сообщение, и так далее. В подобной ситуации нам помогут вложенные условия. Выглядит это так:

Если первая команда вернёт ноль, что говорит о её успешном выполнении, выполнятся команды в первом блоке then , иначе, если первое условие окажется ложным, и если вторая команда вернёт ноль, выполнится второй блок кода.

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

Сравнение чисел

В скриптах можно сравнивать числовые значения. Ниже приведён список соответствующих команд.

n1 -eq n2 Возвращает истинное значение, если n1 равно n2 .
n1 -ge n2 Возвращает истинное значение, если n1 больше или равно n2 .
n1 -gt n2 Возвращает истинное значение, если n1 больше n2 .
n1 -le n2 Возвращает истинное значение, если n1 меньше или равно n2 .
n1 -lt n2 Возвращает истинное значение, если n1 меньше n2 .
n1 -ne n2 Возвращает истинное значение, если n1 не равно n2 .

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

Вот что выведет эта команда.

Сравнение чисел в скриптах

Значение переменной val1 больше чем 5, в итоге выполняется ветвь then оператора сравнения и в консоль выводится соответствующее сообщение.

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

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

str1 = str2 Проверяет строки на равенство, возвращает истину, если строки идентичны.
s tr1 != str2 Возвращает истину, если строки не идентичны.
str1 Возвращает истину, если str1 меньше, чем str2 .
str1 > str2 Возвращает истину, если str1 больше, чем str2 .
-n str1 Возвращает истину, если длина str1 больше нуля.
-z str1 Возвращает истину, если длина str1 равна нулю.

Вот пример сравнения строк в сценарии:

В результате выполнения скрипта получим следующее.

Сравнение строк в скриптах

Вот одна особенность сравнения строк, о которой стоит упомянуть. А именно, операторы «>» и « » как команду перенаправления вывода.

Вот как работа с этими операторами выглядит в коде:

Вот результаты работы скрипта.

Сравнение строк, выведенное предупреждение

Обратите внимание на то, что скрипт, хотя и выполняется, выдаёт предупреждение:

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

Теперь всё работает как надо.

Ещё одна особенность операторов «>» и « myfile , после чего выполним в терминале такую команду:

Она отсортирует строки из файла так:

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

Если его запустить, окажется, что всё наоборот — строчная буква теперь больше прописной.

Команда sort и сравнение строк в файле сценария

В командах сравнения прописные буквы меньше строчных. Сравнение строк здесь выполняется путём сравнения ASCII-кодов символов, порядок сортировки, таким образом, зависит от кодов символов.

Команда sort , в свою очередь, использует порядок сортировки, заданный в настройках системного языка.

Проверки файлов

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

-d file Проверяет, существует ли файл, и является ли он директорией.
-e file Проверяет, существует ли файл.
-f file Проверяет, существует ли файл, и является ли он файлом.
-r file Проверяет, существует ли файл, и доступен ли он для чтения.
-s file П роверяет, существует ли файл, и не является ли он пустым.
-w file Проверяет, существует ли файл, и доступен ли он для записи.
-x file Проверяет, существует ли файл, и является ли он исполняемым.
file1 -nt file2 Проверяет, новее ли file1 , чем file2 .
file1 -ot file2 Проверяет, старше ли file1 , чем file2 .
-O file Проверяет, существует ли файл, и является ли его владельцем текущий пользователь.
-G file Проверяет, существует ли файл, и соответствует ли его идентификатор группы идентификатору группы текущего пользователя.

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

Опробуем одну из команд на практике:

Этот скрипт, для существующей директории, выведет её содержимое.

Вывод содержимого директории

Полагаем, с остальными командами вы сможете поэкспериментировать самостоятельно, все они применяются по тому же принципу.

Итоги

Сегодня мы рассказали о том, как приступить к написанию bash-скриптов и рассмотрели некоторые базовые вещи. На самом деле, тема bash-программирования огромна. Эта статья является переводом первой части большой серии из 11 материалов. Если вы хотите продолжения прямо сейчас — вот список оригиналов этих материалов. Для удобства сюда включён и тот, перевод которого вы только что прочли.

    Bash Script Step By Step — здесь речь идёт о том, как начать создание bash-скриптов, рассмотрено использование переменных, описаны условные конструкции, вычисления, сравнения чисел, строк, выяснение сведений о файлах.

Bash Scripting Part 2, Bash the awesome — тут раскрываются особенности работы с циклами for и while.

Bash Scripting Part 3, Parameters & options — этот материал посвящён параметрам командной строки и ключам, которые можно передавать скриптам, работе с данными, которые вводит пользователь, и которые можно читать из файлов.

Bash Scripting Part 4, Input & Output — здесь речь идёт о дескрипторах файлов и о работе с ними, о потоках ввода, вывода, ошибок, о перенаправлении вывода.

Bash Scripting Part 5, Sighals & Jobs — этот материал посвящён сигналам Linux, их обработке в скриптах, запуску сценариев по расписанию.

Bash Scripting Part 6, Functions — тут можно узнать о создании и использовании функций в скриптах, о разработке библиотек.

Bash Scripting Part 7, Using sed — эта статья посвящена работе с потоковым текстовым редактором sed.

Bash Scripting Part 8, Using awk — данный материал посвящён программированию на языке обработки данных awk.

Bash Scripting Part 9, Regular Expressions — тут можно почитать об использовании регулярных выражений в bash-скриптах.

Bash Scripting Part 10, Practical Examples — здесь приведены приёмы работы с сообщениями, которые можно отправлять пользователям, а так же методика мониторинга диска.

  • Bash Scripting Part 11, Expect Command — этот материал посвящён средству Expect, с помощью которого можно автоматизировать взаимодействие с интерактивными утилитами. В частности, здесь идёт речь об expect-скриптах и об их взаимодействии с bash-скриптами и другими программами.
  • Полагаем, одно из ценных свойств этой серии статей заключается в том, что она, начинаясь с самого простого, подходящего для пользователей любого уровня, постепенно ведёт к довольно серьёзным темам, давая шанс всем желающим продвинуться в деле создания сценариев командной строки Linux.

    Уважаемые читатели! Просим гуру bash-программирования рассказать о том, как они добрались до вершин мастерства, поделиться секретами, а от тех, кто только что написал свой первый скрипт, ждём впечатлений.

    Источник

    Читайте также:  Универсальный драйвер для сканера benq windows
    Оцените статью