Bash-функции и локальные переменные
Эта статья продемонстрирует, как функции локальных переменных используются и создаются в Bash. Создание функций Bash позволяет сделать ваш код более структурированным, а локальные переменные помогают обеспечить безопасность и избежать ошибок в коде. Нырнуть в!
Что такое функции Bash?
Как и другие языки программирования, Bash позволяет создавать функции внутри вашего кода или скрипта. Функция может быть определена для выполнения конкретной задачи или набора задач, и ее можно легко и быстро вызывать из вашего основного кода, просто используя имя, данное функции.
Вы также можете вкладывать вызовы функций (вызов функции из другой функции), использовать локальные переменные внутри функции и даже передавать переменные туда и обратно с функциями или с помощью глобальных переменных. Давайте исследовать.
Простая функция Bash
Мы определяем test.sh с помощью нашего текстового редактора следующим образом:
#!/bin/bash welcome(){ echo "welcome" } welcome
Затем мы делаем этот файл исполняемым, добавляя свойство execute (x
) и выполняем скрипт:
chmod +x test.sh ./test.sh
Мы можем видеть, как скрипт сначала определяет функцию welcome()
, используя идиомы Bash function_name()
и {
…}
функциональные оболочки. Наконец, мы вызываем функцию welcome, просто используя ее имя welcome
.
Когда скрипт выполняется, в фоновом режиме происходит то, что определение функции отмечается, но пропускается (т. е. не выполняется), пока немного ниже не будет нажат вызов функции welcome
, Интерпретатор Bash выполняет функцию welcome
и возвращается к строке сразу после последующего вызова функции, что в данном случае является концом нашего скрипта.
Передача переменных в функции Bash
Мы определяем файл test2.sh с помощью нашего любимого текстового редактора (vi ;) следующим образом:
#!/bin/bash if [ -z "${1}" ]; then echo "One option required!" exit 1 fi func1(){ echo "${1}" } func2(){ echo "${2} ${1}" } func1 "${1}" func2 "a" "b"
Мы снова делаем наш скрипт исполняемым с помощью chmod +x test2.sh
и выполняем то же самое.
Полученный результат может показаться интересным или даже запутанным поначалу. Тем не менее, это логично и легко следовать. Первый параметр, переданный сценарию, будет глобально доступен внутри кода как $ {1}
, за исключением внутренних функций, где $ {1}
становится первым параметром, переданным функции, $ {2}
— вторым и т. д.
Другими словами, глобальная переменная $ {1}
(первая опция, переданная сценарию из командной строки) недоступна внутри функций, где значение 36 Переменная {1}
изменяется на первую опцию, переданную функции. Подумайте об иерархии или подумайте о том, как функция может представлять небольшой сценарий сама по себе, и вскоре это обретет смысл.
В качестве примечания можно также использовать $1
вместо $ {1}
, но я настоятельно рекомендую начинающим кодировщикам Bash всегда окружать имена переменных {
и .
Причина в том, что иногда, например, при использовании переменных в строке, интерпретатор Bash не может видеть, где заканчивается переменная, и часть примыкающего текста может быть воспринята как часть имени переменной. там, где это не так, что приводит к неожиданному результату. Это также чище и яснее, каково намерение, особенно когда речь идет о массивах и флагах специальных опций.
Таким образом, мы начинаем нашу программу с глобальной переменной $ {1}
, для которой задано значение \first\
. Если вы посмотрите на вызов func1
, вы увидите, что мы передаем эту переменную в функцию, таким образом, $ {1}
внутри функции становится тем, что было в $ {1}
программы, т.е. \first\
, поэтому первая строка вывода действительно first
.
Затем мы вызываем func2
и передаем в функцию две строки \a\
и \b\
. Затем они автоматически становятся $ {1}
и $ {2}
внутри функции func2
. Внутри функции мы печатаем их в обратном порядке, и наш вывод хорошо совпадает с b a
в качестве второй строки вывода.
Наконец, мы также делаем проверку в верхней части нашего скрипта, которая гарантирует, что опция действительно передается в скрипт test2.sh
, проверяя, \$ {1}\
пуст или не использует тест -z
внутри команды if
. Мы выходим из скрипта с ненулевым кодом выхода (exit 1
), чтобы указать всем вызывающим программам, что что-то пошло не так.
Локальные переменные и возвращаемые значения
Для нашего последнего примера мы определяем сценарий test3.sh следующим образом:
#!/bin/bash func3(){ local REVERSE="$(echo "${1}" | rev)" echo "${REVERSE}" } INPUT="abc" REVERSE="$(func3 "${INPUT}")" echo "${REVERSE}"
Снова делаем его исполняемым и выполняем скрипт. Результатом будет cba
, как и следовало ожидать, просмотрев код и отметив имена переменных и т. д.
Однако код сложный и требует некоторого привыкания. Давайте исследовать.
Во-первых, мы определяем функцию func3
, в которой мы создаем локальную переменную с именем REVERSE
. Мы присваиваем ей значение, вызывая подоболочку ($()
), и внутри этой подоболочки мы повторяем все, что было передано функции ($ {1}
) и передайте этот вывод команде rev
.
Команда rev
выводит ввод, полученный из канала (или иным образом), в обратном порядке. Также интересно отметить, что переменная $ {1}
остается внутри подоболочки! Это прошлое интегрально.
Затем, все еще из функции func3
, мы печатаем вывод. Однако этот вывод не будет отправлен на экран, а будет захвачен самим вызовом нашей функции и, таким образом, сохранен в переменной ‘global’ REVERSE
.
Мы устанавливаем наш ввод в \abc\
, снова вызываем функцию func3
из подоболочки, передавая переменную INPUT
, и присваиваем вывод в переменную REVERSE
. Обратите внимание, что между переменной 'global' REVERSE
и переменной local REVERSE
внутри скрипта нет абсолютно никакой связи. .
В то время как любая глобальная переменная, включая любую REVERSE, будет передана функции, как только будет определена локальная переменная с тем же именем, локальная переменная будет использоваться. Мы также можем проверить и увидеть это еще один небольшой скрипт test4.sh:
#!/bin/bash func3(){ local REVERSE="$(echo "${1}" | rev)" echo "${REVERSE}" } INPUT="abc" REVERSE="test" func3 "${INPUT}" echo "${REVERSE}"
При выполнении выводятся cba
и test
. cba
на этот раз генерируется тем же echo \$ {REVERSE}\
внутри функции func3
, но на этот раз выводить напрямую, а не захватывать в приведенном ниже коде, поскольку функция func3 \$ {INPUT}\
не вызывается из подоболочки.
Этот сценарий подчеркивает два момента обучения, которые мы рассмотрели ранее: во-первых, несмотря на то, что мы установили переменную REVERSE
в значение \test\
внутри сценария перед вызовом функция func3
– что локальная переменная REVERSE
берет верх и используется вместо 'глобальной'.
Во-вторых, наша переменная 'global' REVERSE
сохраняет свое значение, даже если внутри вызываемой функции использовалась local переменная с таким же именем. функция3
.
Подведение итогов
Как видите, функции Bash, передача переменных, а также использование локальных и полуглобальных переменных делают язык сценариев Bash универсальным, простым в кодировании и дают вам возможность определять хорошо структурированный код.
Здесь также следует отметить, что помимо улучшенной читаемости кода и простоты использования, использование локальных переменных обеспечивает дополнительную безопасность, поскольку переменные не будут доступны вне контекста функции и т. д. Наслаждайтесь функциями и локальными переменными при написании кода в Баш!
Если вы хотите узнать больше о Bash, ознакомьтесь с нашими статьями «Как правильно анализировать имена файлов в Bash» и «Использование xargs в сочетании с bash -c для создания сложных команд».