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

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

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

  • Передаваемые параметры , , … , соответствующее положению параметра после имени функции.
  • Переменная зарезервирована для имени функции.
  • Переменная  содержит число позиционных параметров/аргументов, передаваемых функции.
  • Переменная или  содержит все позиционные параметры/аргументы, переданные функции.

Вот пример:

~ / Passing_arguments.sh

#!/bin/bash

greeting () {
  echo "Привет $1"
}

greeting "AndreyEx"
Привет AndreyEx

Условия

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

#в переменную source засовываем первый параметр скрипта #в переменную dest засовываем второй параметр скрипта

# в ковычках указываем имена переменных для сравнения. -eq — логическое сравнение обозначающие «равны» # если они действительно равны, то #выводим сообщение об ошибке, т.к. $source и $dest у нас равны # выходим с ошибкой (1 — код ошибки) # если же они не равны # то выполняем команду cp: копируем источник в приемник #обозначаем окончание условия.

Результат выполнения скрипта:

Структура  используется следующим образом:

 <команда или набор команд возвращающих код возврата(0 или 1)> <если выражение после if истино, то выполняется этот блок> <если выражение после if ложно, тот этот>

В качестве команд возвращающих код возврата могут выступать структуры  или любая другая(или несколько) linux-команда.

 — используется для логического сравнения. после выражения, неоьбходима закрывающая скобка «]» — синоним команды test — расширенная версия «]» — математическое сравнение.

для построения многоярусных условий вида:

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

Декларация функции Bash

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

  1. Первый формат начинается с имени функции, за которым следуют скобки. Тело функции должно быть заключено в фигурные скобки .
    function_name () {
      commands
    }

    Однолинейная версия:

    function_name () { commands; }
  2. Второй формат начинается с зарезервированного слова , за которым следует имя функции. Фигурные скобки  не являются обязательными.
    function function_name {
      commands
    }

    Однолинейная версия:

    function function_name { commands;}

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

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

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

~ / Hello_world.sh

#!/bin/bash
hello_world () {
    echo 'hello, world'
}
hello_world

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

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

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

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

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

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

Вот пример:

~ / Passing_arguments.sh

Переменные

  • Используйте ключевое слово read в скрипте, чтобы запросить данные у пользователя, запускающего скрипт.
  • Используйте подстановку команд, чтобы использовать результат команды и назначить его переменной. Например, команда date +%d-%m-%y показывает текущую дату в формате день-месяц-год. Чтобы сделать это в сценарии, вы можете использовать TODAY=$(date +%d-%m-%y). Для подстановки команд вам просто нужно поместить команду, результат которой вы хотите использовать, между скобками.

Листинг 3.read

if… then… else… fi $1test test if …-z $1 — на самом деле тремя (прим. переводчика)-z test$1 if $1then test then testthen echoreadread read TEXT elseelse $1fiechoВы можете попрактиковаться на этом примере при работе с вводом.

  1. Откройте редактор и создайте файл с именем text. Введите содержимое кода из листинга 3 в этот файл.
  2. Запишите файл на диск и выполните chmod +x text, чтобы сделать его исполняемым.
  3. Запустите скрипт, выполнив ./text и без дополнительных аргументов. Вы увидите, что он запрашивает ввод.
  4. Запустите скрипт, используя «hello» в качестве аргумента (./text hello). Результат отобразит «you have entered the text hello» в STDOUT.

Как передать аргументы в функцию в Bash

Как мы уже выяснили, вызов функций в Bash больше похож на вызов команд оболочки, а не на вызов функций в привычном нам виде. Это справедливо и для передачи аргументов — их не нужно помещать в круглые скобки, их достаточно просто перечислить через пробел. Примерно как вы бы передали опции команде оболочки (например, ls -l). По сути, аргументы функции в bash обрабатываются как позиционные параметры ($1, $2..$9, ${10}, ${11}, и так далее).

Допустим, функция объявлена следующим образом:

function ИМЯ_ФУНКЦИИ {
	КОМАНДЫ...
} 

Или так:

function_name () {
	ИМЯ_ФУНКЦИИ...
} 

Для вызова функции с аргументами:

ИМЯ_ФУНКЦИИ "$arg1" "$arg2"

Функция ссылается на переданные аргументы по их позиции (не по имени), то есть $1, $2 и так далее. $0 — это имя самого скрипта.

Пример:

function_name () {
	echo "Параметр #1 это $1"
}

Обратите внимание, что внутри функции вместо $* (означает все аргументы) нужно использовать $@. То есть обрабатывать аргументы можно примерно так.

function callingSomeFunction ()
{
	for value in "$@" # Используйте здесь "$@", а не "$*" !!!!!
	do
		:
	done
}

Помните об области видимости переменных в функции! $1 за пределами функции и $1 внутри функции — это совершенно разные вещи! За пределами функциями $1 — это первый аргумент, переданный всему скрипту. А внутри функции $1 — это первый аргумент, переданный функции!

Можно использовать имена для переменных:

declare filename=$1 # declare даёт вам больше опций и ограничивает область видимости переменных

Как передать массив в качестве аргумента в функцию в Bash:

callingSomeFunction "${someArray}" # Расширяется на все элементы массива.

Нужно передать величину и массив, но ещё и использовать «$@» внутри функции? Тогда так:

function linearSearch ()
{
    declare myVar="$1"

    shift 1 # удаляет $1 из списка параметров

    for value in "$@" # представляет оставшиеся параметры.
    do
        if ]
        then
            echo -e "Found it!\t... after a while."
            return 0
        fi
    done

    return 1
}

linearSearch $someStringValue "${someArray}"

Чтение из STDIN

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

Баш вмещает трубопроводы и перенаправление посредством специальных файлов. Каждый процесс получает собственный набор файлов (один для STDIN, STDOUT и STDERR соответственно), и они связаны при вызове или перенаправлении. Каждый процесс получает следующие файлы:

  • STDIN — /proc/<processID>/fd/0
  • STDOUT — /proc/<processID>/fd/1
  • STDERR — /proc/<processID>/fd/2

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

  • STDIN — /dev/stdin or /proc/self/fd/0
  • STDOUT — /dev/stdout or /proc/self/fd/1
  • STDERR — /dev/stderr or /proc/self/fd/2

fd в дорожках выше обозначает дескриптор файла.

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

summary

Shell

#!/bin/bash
# Основное резюме моего отчета о продажах

echo Here is a summary of the sales data:
echo ====================================
echo

cat /dev/stdin | cut -d’ ‘ -f 2,3 | sort

1
2
3
4
5
6
7
8

#!/bin/bash
# Основное резюме моего отчета о продажах
 

echoHere isasummary of the sales data

echo====================================

echo
 

catdevstdin|cut-d’ ‘-f2,3|sort

Давайте разберем это:

  • Строки 4, 5, 6 — Распечатайте заголовок для вывода
  • Строка 8 — cat файл, представляющий STDIN, вырезает установку разделителя на пробел, поля 2 и 3 затем сортируют вывод.

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

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

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

~ / Return_values.sh

#!/bin/bash

my_function () {
  echo "некоторый результат"
  return 23
}

my_function
echo $?
некоторый результат
23

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

~ / Return_values.sh

#!/bin/bash

my_function () {
  func_result="некоторый результат"
}

my_function
echo $func_result
некоторый результат

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

~ / Return_values.sh

#!/bin/bash

my_function () {
  local func_result="некоторый результат"
  echo "$func_result"
}

func_result="$(my_function)"
echo func_result
некоторый результат

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

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

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

Для демонстрации давайте взглянем на следующий сценарий bash iseven.sh :

#!/bin/bash

iseven () {
if ; then
echo "$1 is even."
else
echo "$1 is odd."
fi
}

iseven 3
iseven 4
iseven 20
iseven 111

Функция iseven () проверяет, является ли число четным или нечетным. Мы сделали четыре вызова функций для iseven(). Для каждого вызова функции предоставили одно число, которое является первым дополнением к функции iseven() и на которое ссылается переменная $ 1 в определении функции.

Давайте запустим bash-скрипт iseven.sh, чтобы убедиться, что он работает:

destroyer@andreyex:~$ ./iseven.sh
3 is odd.
4 is even.
20 is even.
111 is odd.

Вы также должны понимать, что аргументы функции bash и аргументы сценария bash – это две разные вещи. Чтобы противопоставить разницу, взгляните на следующий сценарий bash funarg.sh :

#!/bin/bash

fun () {
echo "$1 is the first argument to fun()"
echo "$2 is the second argument to fun()"
}

echo "$1 это первый аргумент к сценарию."
echo "$2 это второй аргумент к сценарию."

fun Yes 7

Запустите скрипт с парой аргументов и посмотрите на результат:

destroyer@andreyex:~$ ./funarg.sh Cool Stuff
Cool это первый аргумент к сценарию.
Stuff это второй аргумент к сценарию.
Yes is the first argument to fun()7 is the second argument to fun()

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

Передача аргументов

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

  • Переданные параметры $1, $2, $3 … $n, соответствуют номеру параметра по порядку, заданными после имени функции.
  • Переменная $0 зарезервирована для имени функции.
  • Переменная $# содержит общее количество аргументов, переданных функции.
  • Переменная $* или $@ содержит все параметры, переданные функции.

Пример передачи аргументов:

#!/bin/bash

greeting () {
  echo "Привет, $1"
}

greeting "Алиса"

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

Привет, Алиса

Теперь у вас есть некоторые знания для того, чтобы правильно писать функции bash.

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

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

useradd lisauseraddlisa $1$2Листинг 1

lisalori bob

Листинг 2

В Листинге 2 представлены два новых элемента, которые относятся к аргументам:

  • $# — это счетчик, который показывает, сколько аргументов было использовано при запуске скрипта.
  • $@ — список всех аргументов, которые использовались при запуске скрипта.

forfor for i in $@$@$ido doneecho Давайте попробуем воспользоваться скриптом из листинга 2 в этом примере:

  1. Введите vi argument, чтобы создать файл argument и скопируйте содержимое из скрипта листинга 2 в этот файл.
  2. Сохраните файл и сделайте его исполняемым.
  3. Запустите команду ./argument a b c. Вы увидите, что отобразятся три строки.
  4. Запустите команду ./argument a b c d e f. Вы увидите, что помимо a b c отобразятся и d e f.

Использование условий и циклов

  • if… then… else — используется для выполнения кода, если определенное условие выполняется
  • for — используется для выполнения команд для диапазона значений
  • while — используется для выполнения кода, если выполняется определенное условие
  • before — используется для выполнения кода, пока не выполнено определенное условие
  • case — используется для оценки ограниченного количества конкретных значений

if then elsetestif if… then… fi

else if elsetestЛистинг 4 if then else

|| и &&

if… then||&&||&&Рассмотрим эти две строки:

$1ping pingif &&||if… then… else&& ||Упражнение if… then… else

  1. Запустите редактор и создайте скрипт с именем filechk.
  2. Скопируйте содержимое из листинга 4 в этот скрипт.
  3. Запустите с ним пару тестов, такие как ./filechk /etc/hosts, ./filechck /usr, ./filechk non-existing-file.

Автодополнение

Tab – автодополнение (в контексте)

Во многих командных интерпретаторах (и в bash в том числе) используется такая возможность, как автодополнение. Как минимум нужно знать, что по нажатию клавиши дописывается название команды. В bash по умолчанию обычно настроено так, что если имеется только один вариант дополнения, то он дописывается по нажатию (также можно использовать и ). Когда вариантов дополнения много, то по первому нажатию дописывается только общая часть (если она есть). А по второму нажатию отображается список всех доступных вариантов. Дальше можно набрать еще символов – уточнить, какое из дополнений нужно, и снова нажать . То же самое с другими дополнениями: имен файлов, имен переменных.

^^^ Здесь, например, смотрю (нажав дважды ), что есть несколько команд, начинающихся с «if», добавив «c» и нажав , получаю набранной команду «ifconfig».

^^^ В этом примере дополняю аргументы команды (здесь имена файлов). Также видно, что в случае, когда вариантов много и все не умещаются в окне терминала, их список отображается утилитой для постраничного просмотра (также при очень большом списке вариантов выдается запрос вида «Display all 125 possibilities? (y or n)» или, как в этом примере, при малом количестве — «—More—».

Дополнения имен пользователей, переменных

Часто, когда дописываются аргументы команд по , дописываются имена файлов. Но стоит также отметить, что, в зависимости от контекста, по дописываются и имена переменных (аргументы, начинающиеся с символа «$»), имена пользователей (аргументы, начинающиеся с символа «~»),…

^^^ Здесь, чтобы набрать «$HISTFILESIZE», вместо 13 символов набрал 8 символов ( ). Помимо того, что так быстрее, это еще и позволяет допускать меньше ошибок при наборе команд, так как не просто печатаю текст, а выбираю из списка установленных переменных.

^^^ Здесь дописываю имена пользователей (фактически пишу адрес домашней директории).

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

Список того, что может дополнять bash, можно посмотреть командой:

Так, например, видно, что:

  • – покажет список имен пользователей, начинающихся с набранных символов, а дополнить комбинацией ;

  • – список имен машин (согласно /etc/hosts), начинающихся с набранных символов, а дополнить – ;

  • – список имен переменных, заданных в этой сессии (можно их также посмотреть командой set), а дополнить – ;

  • – список команд (согласно доступных: $PATH, alias, функций, встроенных команд), а дополнить – ;

  • – список имен файлов, а дополнить – .

Alt-* – вставить дополнения, Ctrl-x * – развернуть шаблон

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

В примерах ниже разворачиваю список файлов:

Вариант с :

Вариант с :

– развернет уже написанный в командной строке шаблон, как в примере ниже:

Создание функций в bash

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

function_name () {
commands
}

Вторая менее часто используемая функция создания bash-функций начинается с зарезервированной рабочей функции, за которой следует имя функции, как показано ниже:

function function_name {
commands
}

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

  • Функция никогда не будет запускаться/выполняться, если вы не вызовете функцию.
  • Определение функции должно предшествовать любым вызовам функции.

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

Взгляните на следующий сценарий bash fun.sh :

#!/bin/bash

hello () {
echo "Hello World"
}

hello
hello
hello

Мы определили функцию с именем hello, которая просто выводит на терминал строку «Hello World». Обратите внимание, что мы сделали три вызова функции hello, и поэтому, если вы запустите сценарий, вы увидите, что на экране трижды напечатана строка «Hello World»:

destroyer@andreyex:~$ ./fun.sh
Hello World
Hello World
Hello World

Объявление функции Bash

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

  1. Формат может начинаться с имени функции, за которым следуют круглые скобки. Это предпочтительный и наиболее популярный формат.
    function_name () {
      commands
    }

    Этот же код можно написать в одну строку:

    function_name () { commands; }
  2. Второй формат начинается с зарезервированного слова function, за которым следует имя функции.
    function function_name {
      commands
    }

    Версия в одну строку:

    function function_name { commands; }

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

  • Список команд, находящихся между фигурными скобками {} — это тело функции. Фигурные скобки, окружающие тело функции, должны быть отделены от тела пробелами или начинаться с новой строки.
  • Простое определение функции не выполняет её. Чтобы вызвать функцию bash, просто используйте имя созданной функции. Команды между фигурными скобками выполнятся, когда функция вызывается через shell оболочку.
  • Соблюдайте порядок написания кода. Определение функции должно быть перед её вызовом.
  • При использовании одно-строчных функций необходимо установить точку с запятой у последней команды.
  • Старайтесь давать имена, которые описывают процесс происходящий внутри тела функции. Чтобы в будущем понимать что делает программный код, взглянув лишь на название.

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

#!/bin/bash

hello_world () {
   echo 'привет, мир'
}

hello_world

Проанализируем написанный код:

  • В третьей мы определяем функцию с именем hello_world и открывая фигурную скобку {, которая отмечает начало тела функции.
  • Строка 4 — это тело функции. Обычно, тело занимает более одной строки.
  • В пятой строке стоит закрывающая фигурная скобка }. Она определяет конец функции.
  • В строке 7 мы выполняем созданную функцию. Выполнять ее можно столько раз, сколько вам нужно.

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

привет, мир

Возврат значений функции в bash

Во многих языках программирования функции возвращают значение при вызове; однако это не относится к bash, поскольку функции bash не возвращают значения.

Когда функция bash завершает выполнение, она возвращает статус выхода последней выполненной команды, записанный в $? переменная. Ноль указывает на успешное выполнение или ненулевое положительное целое число (1-255) указывает на сбой.

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

#! /bin/bash

error () {
blabla
return 0
}

error
echo "Состояние возвращаемого значения ошибки функции: $?"

Если вы запустите bash-скрипт error.sh , вы можете быть удивлены результатом:

destroyer@andreyex:~$ ./error.sh
./error.sh: line 4: blabla: command not found
Состояние возвращаемого значения ошибки функции: 0

Без оператора return 0 функция ошибки никогда бы не вернула ненулевой статус выхода, поскольку blabla приводит к ошибке команда не найдена .

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

Вы также должны знать, что оператор return немедленно завершает функцию.

Область переменных

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

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

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

~ / Variables_scope.sh

#!/bin/bash

var1='A'
var2='B'

my_function () {
  local var1='C'
  var2='D'
  echo "Внутренняя функция: var1: $var1, var2: $var2"
}

echo "Перед выполнением функции: var1: $var1, var2: $var2"

my_function

echo "После выполнения функции: var1: $var1, var2: $var2"

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

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

Перед выполнением функции: var1: A, var2: B
Внутренняя функция: var1: C, var2: D
После выполнения функции: var1: A, var2: D

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

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

Двойные скобки

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

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

Рассмотрим примеры в скрипте

expansion_example.sh

Разберём этот скрипт:

Строка 4 — Базовый синтаксис. Можно ставить пробелы без использования кавычек.

Строка 7 — Работает и без пробелов.

Строка 10 — Можно использовать переменные без $ перед ними.

Строка 13 — А можно и с $

Строка 16 — Увеличение переменной на 1. Символ $ не нужен.

Строка 19 — Увеличение переменной на 3. Это краткая форма записи b = b &plus; 3.

Строка 19 — В отличие от других способов символ * не нужно экранировать.

./expansion_example.sh

981112131620

Двойные скобки дают довольно много свободы в форматировании кода.

Они доступны в Bash по умолчанию и их эффективность немного выше. Хотя заметить разницу на современных компьютерах будет непросто.

История команд

«Работа с историей команд» – классическая тема обычно из любого начального курса по Linux (по крайней мере, среди тех курсов, которые читаются у нас в «Сетевой Академии ЛАНИТ»). И многие, кто имеет хотя бы небольшой опыт работы с командной строкой, историей команд пользуются – как минимум знают, что она есть, и используют стрелки «вверх» (отобразить предыдущую команду) и «вниз» (отобразить следующую после отображаемой команду в истории команд), чтобы выбрать, какую из ранее введенных команд либо снова выполнить, либо подредактировать и запустить отредактированную. Но помимо стрелок еще есть ряд полезных комбинаций клавиш, которые позволяют работать с историей команд, – быстрее находить нужные команды.

Ctrl-r – Поиск по истории

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

^^^ В этом примере мне понадобилось из истории вытащить команду, содержащую текст «su»: нажав и набрав искомый текст «su», я увидел самую недавнюю команду, содержащую «su»; при повторном нажатии отображается предыдущая команда, содержащая «su» и т.д. При необходимости изменить команду жму стрелку «вправо» и правлю текст, а чтобы запустить команду — нажимаю .

PgUp/PgDown – Поиск по истории

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

^^^ В этом примере перемещаюсь между командами, начинающимися с «cat». (Часто также ищу команды, начинающиеся с «sudo». Или если мне нужно снова отредактировать какой-то файл, который недавно редактировал: набираю «vi», жму несколько раз , а затем .)

Alt-_/Alt-./Alt— – вставка аргументов

Комбинация (выполняется нажатием , , ) – вставляет последний аргумент из предыдущих команд. (Аналогично работает комбинация или, что то же самое, )

^^^ В данном примере видно, как повторные нажатия вставляют аргументы от пред-пред-…-идущих команд.

Комбинация – позволяет указать (порядковый номер с конца), какой аргумент вставить клавишей из предыдущей команды.

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

Alt-# – текущую команду преобразовать в комментарий

Бывает, во время набора очень длинной команды понимаю, что мне нужно что-нибудь посмотреть или дополнительно сделать (например, глянуть, какие файлы есть в определенной директории, прочитать мануал по команде, установить нужный пакет…). Что делать с уже набранным текстом? Хотелось бы посмотреть нужную информацию и продолжить набирать команду, а не начинать печатать её сначала. (выполняется нажатием , , . Также можно использовать ) – преобразует текущую набранную команду в комментарий в истории – добавляет символ «#» в начало строки и добавляет полученную строку в историю команд.

Ctrl-o – повтор команд из истории

Комбинация позволяет повторять серию команд из истории. То есть нужно из истории команд стрелками выбрать первую команду из серии и нажать – это выполнит текущую команду и выведет из истории следующую. Дальше можно продолжать нажимать с тем же эффектом.

^^^ В примере я написал три команды: одна увеличивает на 1 переменную, которой соответствует год; вторая выводит переменную-год; третья показывает, сколько дней в феврале в указанном году. Дальше, нажимая , повторяю эту серию из трех команд много раз (один кадр соответствует трем нажатиям).

Вступление

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

if ; then

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

if test $foo -ge 3; then

Если $foo больше(G) или равно(E) 3, блок после «then» будет выполнен. Если вы всегда задавались вопросом, почему bash использует или вместо >= или ==, это потому, что этот тип условия исходит из команды, где и — параметры.
И это то, что по сути, проверяет состояние завершения команды. Я объясню это более подробно далее в руководстве.
Также есть встроенные проверки, которые более специфичны для оболочек.

if ; then

Вышеуказанное условие выполняется, если файл «regularfile» существует и
это обычный файл. Обычный файл означает, что это не блок или
символьное устройство или каталог. Таким образом, вы можете быть уверены, что
Файл существует, прежде чем что-то делать с ним. Вы даже можете проверить, если
файл читабелен!

if ; then

Приведенное выше условие выполняется, если файл «readablefile» существует и доступен для чтения. Легко, не правда ли?

Объем переменных

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

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

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

~/variables_scope.sh

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

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

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

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

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

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

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

~ / Return_values.sh

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

~ / Return_values.sh

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

~ / Return_values.sh

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

Написание функций Bash

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

Синтаксис создания функции очень прост:

имя_функции() { список_команд }

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

Простая функция

Давайте напишем небольшую функцию, которая будет выводить строку на экран:

$ vi function.sh

#!/bin/bash
printstr(){
echo «hello world»
}
printstr

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

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

Аргументы функции

Аргументы функции нужно передавать при вызове, а читаются они точно так же, как и аргументы скрипта. Синтаксис вызова функции с параметрами bash такой:

имя_функции аргумент1 аргумент2 … аргументN

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

Можно сделать, чтобы параметров было несколько:

Есть и другой способ извлекать аргументы, как в Си, с помощью стека. Мы извлекаем первый аргумент, затем сдвигаем указатель стека аргументов на единицу и снова извлекаем первый аргумент. И так далее:

Возврат результата функции

Вы можете не только использовать функции с параметрами bash, но и получить от нее результат работы. Для этого используется команда return. Она завершает функцию и возвращает числовое значение кода возврата. Он может быть от 0 до 255:

Если вам нужно применить возврат значения функции bash, а не статус код, используйте echo. Строка не сразу выводится в терминал, а возвращается в качестве результата функции и ее можно записать в переменную, а затем использовать:

Экспорт функций

Вы можете сделать функцию доступной вне скрипта с помощью команды declare:

Затем запустите скрипт с помощью команды source:

Рекурсия

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

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

Локальные переменные в функции

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

Библиотеки функций

Мы можем взять некоторые функции bash и объединить их в одну библиотеку, чтобы иметь возможность одной командой импортировать эти функции. Это делается похожим образом на экспорт функций. Сначала создадим файл библиотеки:

test1(){
echo «Hello World from 1»;
}
test2(){
echo «Hello World from 2»;
}
test3(){
echo «Hello World from 3»;
}

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

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Ваша ОС
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: