<!--
.. title: Функции в bash
.. slug: bash-functions
.. date: 2025-10-09 13:42:46 UTC+03:00
.. tags: bash, linux
.. category: linux 
.. link: 
.. description: 
.. type: text
-->

## Задать функцию

Функции в bash можно задавать двумя способами:

```bash
# Способ 1
function_name () {
  commands
}

# Способ 2
function function_name {
  commands
}

```

Простые функции можно объявлять в одну строку.
При этом пробелы между 
фигурными скобками и телом функции важны!.
И последним в теле должен быть `;` (точка с запятой).

Объявление функций в одну строку:

```bash
# Способ 1
function_name () { commands; }

# Способ 2
function function_name { commands; }

```
Итого по объявлению функций:

* Тело функций (всё что между фигурными скобками) должно отделяться от самих фигурных скобок
переносом строки или пробелами;
* Определение функции не вызывает её (как и в нормальных языках);
* Определение функции должно быть выше чем её вызовы;
* Тело однострочных функций должно заканчиваться `;` (точкой с запятой).

## Переменные

Глобальные переменные видны в функциях и могут быть модифицированы в функциях.
Локальные переменные (область видимости внутри функции) должны объявляться
с ключевым словом `local`.

Локальные переменные имеют приоритет над глобальными если используется одно
и то же имя.

```bash
#!/bin/bash

var1='A'
var2='B'

my_function () {
  local var1='C'
  var2='D'
  echo "Inside function: var1: $var1, var2: $var2"
}

echo "Before executing function: var1: $var1, var2: $var2"

my_function

echo "After executing function: var1: $var1, var2: $var2"

```
Вывод этого скрипта:

```
Before executing function: var1: A, var2: B
Inside function: var1: C, var2: D
After executing function: var1: A, var2: D
```

## Параметры

Чтобы передать параметры в функцию надо просто написать их после вызова,
разделяя пробелами. 
Имеет смысл заключать их в кавычки, тогда можно передавать параметры
с пробелами.

* Внутри функции доступ к параметрам осуществляется через переменные
`$1`, `$2`, `$3` и т.д.
* Переменная `$0` содержит имя самой функции.
* Переменная `$#` содержит количество переданных параметров.
* Переменные `$*` и `$@` содержать все парамеры, переданные функцию.

### Отличия переменных `$*` и `$@`

* Если эти переменные НЕ заключать в кавычки, то они эквивалентны;
* В кавычках `"$*"` раскрывается в одну строку `"$1 $2 ... $n"`;
* В кавычках `"$@"` раскрывается в разные строки `"$1" "$2" ... "$n"`.

Пример:

```bash
#!/bin/bash

greeting () {
  echo "Hello $1"
}

greeting "World"
```

## Возвращаемые значения

В отличие от функций в "настоящих" языках программирования, 
функции в Bash не позволяют возвращать значения как это принято. 
Когда функция bash заканчивает выполнение, ее возвращаемое значение
это статус последней выполненной команды в теле функции, 
обычно 0 при успешном завершении, число 1-255 код ошибки.

Это число можно указать явно при использовании команды `return`, 
после чего оно будет сохранено в специальной переменной `$?`. 
Команда `return` прерывает выполнение функции (как и в обычных языках),
а код ошибки можно рассматривать как статус выполнения. 

Пример:

```bash
#!/bin/bash

my_function () {
  echo "some result"
  return 55
}

my_function
echo $?
```

Вывод этого скрипта:

```
some result
55
```
Чтобы по-настоящему что-то вернуть из функции надо использовать что-то другое.
Самый простой вариант - присвоить что-то глобальной переменной:

```bash
#!/bin/bash

my_function () {
  func_result="some result"
}

my_function
echo $func_result
```

Вывод этого скрипта:

```
some result
```

Есть способ получше. Отправить требуемое возвращаемое значение
на вывод (при помощи `echo` или `printf`, например):

```bash
#!/bin/bash

my_function () {
  local func_result="some result"
  echo "$func_result"
}

func_result="$(my_function)"
echo $func_result
```

Вывод этого скрипта:
```
some result
```

Тут вместо простого вызова (который просто напечатает строку)
вызов функции "оборачивается" в оператор `$(...)`, после чего
переменная будет содержать то, что функция "хотела" напечатать.

## Переопределение команд

Можно сделать функцию с именем, таким же как существующая команда.
В этом случае, вместо команды будет вызываться функция.
так можно добавлять, например, дополнительные опции во все вызовы
команд сразу, или ещё как-то шаманить, чтоб не править много мест 
в скрипте сразу.

Пример:

```bash
#!/bin/bash

#overriding command
echo(){
    builtin echo "The name is : $1"
}

echo "Edward III"
```

Вывод этого скрипта:
```
The name is : Edward III
```
