Пояснення повернення значень у функціях Bash для новачків

26.10.2025 10 хвилин

У цій статті ви дізнаєтесь, як повернути значення з функції в Bash, чим відрізняється команда return від звичайного виводу через echo, і як правильно обробляти коди завершення. Матеріал пояснює, як у Bash-скриптах передавати результати між функціями, уникати типових помилок і використовувати локальні змінні для безпечного коду. Ви навчитеся створювати функції, що повертають не лише статус успіху, а й реальні дані — рядки, числа чи навіть кілька значень одночасно.

Створення вашої першої функції Bash

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

Створення базової функції

Давайте створимо нашу першу функцію Bash. Відкрийте вікно терміналу та введіть:

cd ~/project
mkdir -p bash_functions
cd bash_functions

Тепер створимо просту функцію в новому скрипті. Створіть файл з назвою first_function.shnano:

touch first_function.sh

Додайте до файлу наступний вміст:

#!/bin/bash

## Define a simple greeting function
say_hello() {
  echo "Hello, world!"
}

## Call the function
say_hello

## Define a function that accepts arguments
greet_person() {
  echo "Hello, $1!"
}

## Call the function with an argument
greet_person "Alice"
greet_person "Bob"

Зробіть скрипт виконуваним:

chmod +x first_function.sh

Тепер запустіть скрипт:

./first_function.sh

Ви повинні побачити цей вивід:

Hello, world!
Hello, Alice!
Hello, Bob!

Пояснення синтаксису функцій

У Bash існує два способи визначення функцій:

  1. Використовуючи стандартний синтаксис:

function_name() {
  ## Commands
}
  1. Використання functionключового слова:

function function_name {
  ## Commands
}

Обидва стилі працюють однаково, але перший використовується частіше та сумісний з POSIX.

Доступ до аргументів функції

Усередині функції ви можете отримати доступ до аргументів, переданих функції, за допомогою позиційних параметрів:

  • $1$2$3тощо посилаються на перший, другий, третій аргумент тощо

  • $0посилається на назву функції або назву скрипта

  • $#дає кількість аргументів

  • $@містить усі аргументи як окремі рядки

  • $*містить усі аргументи як один рядок

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

touch function_args.sh

Додайте наступний вміст:

#!/bin/bash

show_args() {
  echo "Function name: $0"
  echo "First argument: $1"
  echo "Second argument: $2"
  echo "Number of arguments: $#"
  echo "All arguments: $@"
}

echo "Calling function with three arguments:"
show_args apple banana cherry

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x function_args.sh
./function_args.sh

Ви повинні побачити результат, подібний до:

Calling function with three arguments:
Function name: ./function_args.sh
First argument: apple
Second argument: banana
Number of arguments: 3
All arguments: apple banana cherry

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

Розуміння кодів повернення функцій

Кожна команда в Bash, включаючи функції, генерує код повернення (також званий кодом виходу). Це числове значення вказує на те, чи команда виконана успішно, чи ні. Цей код повернення є фундаментальним для обробки помилок у скриптах Bash.

Основні коди повернення

У Баші:

  • Код повернення 0вказує на успіх

  • Будь-яке ненульове значення (1-255) вказує на помилку або ненормальний стан

Давайте створимо скрипт, щоб продемонструвати це:

cd ~/project/bash_functions
touch return_codes.sh

Додайте наступний вміст:

#!/bin/bash

## Function that always succeeds
succeed() {
  echo "This function succeeds"
  return 0
}

## Function that always fails
fail() {
  echo "This function fails"
  return 1
}

## Call the functions and check their return codes
succeed
echo "Return code of succeed: $?"

fail
echo "Return code of fail: $?"

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x return_codes.sh
./return_codes.sh

Ви повинні побачити:

This function succeeds
Return code of succeed: 0
This function fails
Return code of fail: 1

Захоплення кодів повернення

Спеціальна змінна $?містить код повернення останньої виконаної команди або функції. Це значення важливе для умовного виконання та обробки помилок.

Давайте створимо ще один скрипт для практики використання кодів повернення для умовної логіки:

touch check_file.sh

Додайте наступний вміст:

#!/bin/bash

## Function to check if a file exists
file_exists() {
  local filename="$1"

  if [ -f "$filename" ]; then
    echo "File $filename exists"
    return 0
  else
    echo "File $filename does not exist"
    return 1
  fi
}

## Test the function with files that exist and don't exist
file_exists "return_codes.sh"
if [ $? -eq 0 ]; then
  echo "Great! The file was found."
else
  echo "Too bad. The file was not found."
fi

echo ""

file_exists "non_existent_file.txt"
if [ $? -eq 0 ]; then
  echo "Great! The file was found."
else
  echo "Too bad. The file was not found."
fi

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x check_file.sh
./check_file.sh

Ви повинні побачити результат, подібний до:

File return_codes.sh exists
Great! The file was found.

File non_existent_file.txt does not exist
Too bad. The file was not found.

Використання кодів повернення в умовних операторах

Код повернення можна використовувати безпосередньо в умовних виразах за допомогою операторів &&(І) та ||(АБО):

touch conditional_return.sh

Додайте наступний вміст:

#!/bin/bash

check_number() {
  local num=$1

  if [ $num -gt 10 ]; then
    return 0 ## Success if number is greater than 10
  else
    return 1 ## Failure if number is not greater than 10
  fi
}

## Using conditional operators with return codes
check_number 15 && echo "Number is greater than 10"
check_number 5 || echo "Number is not greater than 10"

## This line runs only if check_number succeeds
check_number 20 && {
  echo "Number is greater than 10"
  echo "Performing additional operations..."
}

## This line runs only if check_number fails
check_number 3 || {
  echo "Number is not greater than 10"
  echo "Taking alternative actions..."
}

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x conditional_return.sh
./conditional_return.sh

Вихід має бути таким:

Number is greater than 10
Number is not greater than 10
Number is greater than 10
Performing additional operations...
Number is not greater than 10
Taking alternative actions...

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

Робота з користувацькими значеннями, що повертаються

Хоча коди повернення корисні для індикації успіху чи невдачі, вони обмежені числами від 0 до 255. Для повернення фактичних даних з функцій нам потрібно використовувати інші методи.

Спосіб 1: Використання Echo для повернення значень

Найпоширеніший спосіб повернення фактичних значень з функцій – це використання echoабо інших команд виводу, а потім захоплення цього виводу.

Давайте створимо скрипт для демонстрації цієї техніки:

cd ~/project/bash_functions
touch return_values.sh

Додайте наступний вміст:

#!/bin/bash

## Function that returns a value using echo
get_username() {
  echo "labex"
}

## Function that returns a calculated value
add_numbers() {
  local sum=$(($1 + $2))
  echo $sum
}

## Capture the returned values
username=$(get_username)
echo "The username is: $username"

result=$(add_numbers 5 7)
echo "The sum of 5 and 7 is: $result"

## You can also use the returned value directly
echo "Calculating again: $(add_numbers 10 20)"

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x return_values.sh
./return_values.sh

Ви повинні побачити:

The username is: labex
The sum of 5 and 7 is: 12
Calculating again: 30

Спосіб 2: Використання глобальних змінних

Інший підхід полягає у зміні глобальних змінних у функції:

touch global_return.sh

Додайте наступний вміст:

#!/bin/bash

## Declare global variables
FULL_NAME=""
USER_AGE=0

## Function that sets global variables
set_user_info() {
  FULL_NAME="$1 $2"
  USER_AGE=$3

  ## Return success
  return 0
}

## Call the function
set_user_info "John" "Doe" 30

## Use the global variables that were set by the function
echo "Full name: $FULL_NAME"
echo "Age: $USER_AGE"

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x global_return.sh
./global_return.sh

Вихід:

Full name: John Doe
Age: 30

Спосіб 3: Повернення кількох значень

Давайте розглянемо, як повернути кілька значень з функції:

touch multiple_returns.sh

Додайте наступний вміст:

#!/bin/bash

## Function that returns multiple values separated by a delimiter
get_system_info() {
  local hostname=$(hostname)
  local kernel=$(uname -r)
  local uptime=$(uptime -p)

  ## Return multiple values separated by semicolons
  echo "$hostname;$kernel;$uptime"
}

## Capture the output and split it
system_info=$(get_system_info)

## Split the values using IFS (Internal Field Separator)
IFS=';' read -r host kernel up <<< "$system_info"

## Display the values
echo "Hostname: $host"
echo "Kernel version: $kernel"
echo "Uptime: $up"

## Alternative method using an array
get_user_details() {
  local details=("John Doe" "[email protected]" "Developer")
  printf "%s\n" "${details[@]}"
}

## Capture the output into an array
mapfile -t user_details < <(get_user_details)

echo ""
echo "User information:"
echo "Name: ${user_details[0]}"
echo "Email: ${user_details[1]}"
echo "Role: ${user_details[2]}"

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x multiple_returns.sh
./multiple_returns.sh

Вивід має відображати інформацію про вашу систему, а також дані користувача:

Hostname: ubuntu
Kernel version: 5.15.0-1033-azure
Uptime: up 2 hours, 15 minutes

User information:
Name: John Doe
Email: [email protected]
Role: Developer

Фактичне ім’я хоста, версія ядра та час безвідмовної роботи залежатимуть від вашої системи.

Ці методи демонструють різні способи повернення значень з функцій, окрім простих кодів повернення. Кожен підхід має свої переваги залежно від ваших конкретних потреб.

Практичне використання функцій у скрипті

Тепер, коли ми розуміємо, як визначати функції та обробляти значення, які вони повертають, давайте створимо практичний скрипт, який демонструє ці концепції в дії. Ми створимо утиліту для керування файлами, яка використовує функції з різними методами повернення.

Створення утиліти керування файлами

Давайте створимо комплексний скрипт, який виконуватиме різні операції з файлами:

cd ~/project/bash_functions
touch file_manager.sh

Додайте наступний вміст:

#!/bin/bash

## Function to check if a file exists
## Returns 0 if file exists, 1 if it doesn't
file_exists() {
  if [ -f "$1" ]; then
    return 0
  else
    return 1
  fi
}

## Function to get file size in bytes
## Returns the size via echo
get_file_size() {
  if file_exists "$1"; then
    ## Use stat to get file size in bytes
    local size=$(stat -c %s "$1")
    echo "$size"
  else
    echo "0"
  fi
}

## Function to count lines in a file
## Returns line count via echo
count_lines() {
  if file_exists "$1"; then
    local lines=$(wc -l < "$1")
    echo "$lines"
  else
    echo "0"
  fi
}

## Function to get file information
## Returns multiple values using a delimiter
get_file_info() {
  local filename="$1"

  if file_exists "$filename"; then
    local size=$(get_file_size "$filename")
    local lines=$(count_lines "$filename")
    local modified=$(stat -c %y "$filename")
    local permissions=$(stat -c %A "$filename")

    ## Return all info with semicolons as delimiters
    echo "$size;$lines;$modified;$permissions"
  else
    echo "0;0;N/A;N/A"
  fi
}

## Function to create a test file
create_test_file() {
  local filename="$1"
  local lines="$2"

  ## Create or overwrite the file
  > "$filename"

  ## Add the specified number of lines
  for ((i = 1; i <= lines; i++)); do
    echo "This is line $i of the test file." >> "$filename"
  done

  ## Return success if file was created
  if file_exists "$filename"; then
    return 0
  else
    return 1
  fi
}

## Main script execution starts here
echo "File Management Utility"
echo "----------------------"

## Create a test file
TEST_FILE="sample.txt"
echo "Creating test file with 10 lines..."
if create_test_file "$TEST_FILE" 10; then
  echo "File created successfully."
else
  echo "Failed to create file."
  exit 1
fi

## Check if file exists
echo ""
echo "Checking if file exists..."
if file_exists "$TEST_FILE"; then
  echo "File '$TEST_FILE' exists."
else
  echo "File '$TEST_FILE' does not exist."
fi

## Get file size
echo ""
echo "Getting file size..."
size=$(get_file_size "$TEST_FILE")
echo "File size: $size bytes"

## Count lines
echo ""
echo "Counting lines in file..."
lines=$(count_lines "$TEST_FILE")
echo "Line count: $lines"

## Get all file information
echo ""
echo "Getting complete file information..."
file_info=$(get_file_info "$TEST_FILE")

## Split the returned values
IFS=';' read -r size lines modified permissions <<< "$file_info"

echo "File: $TEST_FILE"
echo "Size: $size bytes"
echo "Lines: $lines"
echo "Last modified: $modified"
echo "Permissions: $permissions"

echo ""
echo "File content preview:"
head -n 3 "$TEST_FILE"
echo "..."

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x file_manager.sh
./file_manager.sh

Ви повинні побачити результат, подібний до:

File Management Utility
----------------------
Creating test file with 10 lines...
File created successfully.

Checking if file exists...
File 'sample.txt' exists.

Getting file size...
File size: 300 bytes

Counting lines in file...
Line count: 10

Getting complete file information...
File: sample.txt
Size: 300 bytes
Lines: 10
Last modified: 2023-11-04 12:34:56.789012345 +0000
Permissions: -rwxrwxr-x

File content preview:
This is line 1 of the test file.
This is line 2 of the test file.
This is line 3 of the test file.
...

Точні значення розміру файлу, часу модифікації та дозволів будуть відрізнятися.

Розбирання сценарію

Наша утиліта для керування файлами демонструє кілька ключових концепцій:

  1. Коди повернення – Функції file_exists()and create_test_file()повертають 0 у разі успіху та 1 у разі невдачі.

  2. Повернення значень за допомогою echo – Функції get_file_size()and count_lines()повертають числові значення через echo

  3. Повернення кількох значень – get_file_info()функція повертає кілька значень, використовуючи роздільник

  4. Композиція функцій – деякі функції викликають інші функції, демонструючи, як створювати складну функціональність.

  5. Умовне виконання – скрипт використовує оператори if з кодами повернення для керування потоком програми.

Цей практичний приклад показує, як поєднати різні методи роботи з функціями для створення корисної утиліти. Скрипт демонструє правильну обробку помилок, композицію функцій та різні методи повернення значень.

Обробка помилок та найкращі практики роботи з функціями

У нашому заключному розділі давайте розглянемо методи обробки помилок та найкращі практики для функцій Bash. Правильна обробка помилок має вирішальне значення для створення надійних та зручних у підтримці скриптів.

Створення скрипта з обробкою помилок

Давайте створимо новий скрипт, який демонструє надійну обробку помилок:

cd ~/project/bash_functions
touch error_handling.sh

Додайте наступний вміст:

#!/bin/bash

## Enable error handling
set -e ## Exit immediately if a command exits with non-zero status

## Define a function to log messages
log_message() {
  local level="$1"
  local message="$2"
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message"
}

## Function to validate a number is positive
validate_positive() {
  local num="$1"
  local name="$2"

  ## Check if the argument is a number
  if ! [[ "$num" =~ ^[0-9]+$ ]]; then
    log_message "ERROR" "$name must be a number"
    return 1
  fi

  ## Check if the number is positive
  if [ "$num" -le 0 ]; then
    log_message "ERROR" "$name must be positive"
    return 2
  fi

  return 0
}

## Function that divides two numbers
divide() {
  local numerator="$1"
  local denominator="$2"

  ## Validate inputs
  validate_positive "$numerator" "Numerator" || return $?
  validate_positive "$denominator" "Denominator" || return $?

  ## Check for division by zero
  if [ "$denominator" -eq 0 ]; then
    log_message "ERROR" "Division by zero is not allowed"
    return 3
  fi

  ## Perform division
  local result=$(echo "scale=2; $numerator / $denominator" | bc)
  echo "$result"
  return 0
}

## Function to safely get user input
get_number() {
  local prompt="$1"
  local input

  while true; do
    read -p "$prompt: " input

    if validate_positive "$input" "Input"; then
      echo "$input"
      return 0
    else
      log_message "WARN" "Invalid input. Please try again."
    fi
  done
}

## Disable automatic exit on error for the main script
set +e

## Main script logic
log_message "INFO" "Starting division calculator"

## Test with valid values
result=$(divide 10 2)
exit_code=$?

if [ $exit_code -eq 0 ]; then
  log_message "INFO" "10 / 2 = $result"
else
  log_message "ERROR" "Division failed with code $exit_code"
fi

## Test with invalid values
echo ""
log_message "INFO" "Testing with invalid values"
divide 0 5
log_message "INFO" "Exit code: $?"

divide 10 0
log_message "INFO" "Exit code: $?"

divide abc 5
log_message "INFO" "Exit code: $?"

## Interactive mode
echo ""
log_message "INFO" "Interactive mode"
echo "Let's perform a division. Enter positive numbers."

## Get user input safely
num1=$(get_number "Enter first number")
num2=$(get_number "Enter second number")

## Perform division
result=$(divide "$num1" "$num2")
exit_code=$?

if [ $exit_code -eq 0 ]; then
  log_message "INFO" "$num1 / $num2 = $result"
else
  log_message "ERROR" "Division failed with code $exit_code"
fi

log_message "INFO" "Calculator finished"

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x error_handling.sh
./error_handling.sh

Ви побачите результат, подібний до наведеного нижче, і вам буде запропоновано ввести числа:

[2023-11-04 13:45:23] [INFO] Starting division calculator
[2023-11-04 13:45:23] [INFO] 10 / 2 = 5.00

[2023-11-04 13:45:23] [INFO] Testing with invalid values
[2023-11-04 13:45:23] [ERROR] Numerator must be positive
[2023-11-04 13:45:23] [INFO] Exit code: 2
[2023-11-04 13:45:23] [ERROR] Division by zero is not allowed
[2023-11-04 13:45:23] [INFO] Exit code: 3
[2023-11-04 13:45:23] [ERROR] Numerator must be a number
[2023-11-04 13:45:23] [INFO] Exit code: 1

[2023-11-04 13:45:23] [INFO] Interactive mode
Let's perform a division. Enter positive numbers.
Enter first number:

Введіть число, наприклад 20. Потім вам буде запропоновано ввести друге число:

Enter second number:

Введіть інше число, наприклад 4, і ви повинні побачити:

[2023-11-04 13:45:30] [INFO] 20 / 4 = 5.00
[2023-11-04 13:45:30] [INFO] Calculator finished

Найкращі практики для функцій Bash

На основі наших прикладів, ось деякі найкращі практики роботи з функціями Bash:

  1. Додайте описові коментарі – задокументуйте, що робить кожна функція, її параметри та значення, що повертаються

  2. Використовуйте змістовні назви функцій – вибирайте назви, які чітко вказують на призначення функції

  3. Перевірка вхідних параметрів – перевірка вхідних даних для запобігання помилкам

  4. Використання локальних змінних – запобігання колізіям імен змінних з localключовим словом

  5. Повернути відповідні коди виходу – використовувати звичайні коди повернення (0 для успіху, ненуль для помилок)

  6. Впроваджуйте належну обробку помилок – реєструйте помилки та коректно їх обробляйте

  7. Зосередьтеся на функціях – кожна функція повинна добре виконувати одну річ

  8. Використовуйте композицію функцій – створюйте складну функціональність, комбінуючи простіші функції

  9. Документуйте повернуті значення – Чітко документуйте, як повертаються значення (через echo, код повернення тощо)

  10. Тестування граничних випадків – Переконайтеся, що функції правильно обробляють незвичайні вхідні дані

Дотримуючись цих практик, ви можете створювати надійніші, зручніші в обслуговуванні та повторно використовувані функції Bash.

Створення бібліотеки функцій

Для останньої вправи створимо бібліотеку функцій багаторазового використання:

touch math_functions.lib

Додайте наступний вміст:

#!/bin/bash
## math_functions.lib - A library of mathematical functions

## Add two numbers
add() {
  echo $(($1 + $2))
}

## Subtract second number from first
subtract() {
  echo $(($1 - $2))
}

## Multiply two numbers
multiply() {
  echo $(($1 * $2))
}

## Divide first number by second (with decimal precision)
divide() {
  if [ "$2" -eq 0 ]; then
    return 1
  fi
  echo "scale=2; $1 / $2" | bc
  return 0
}

## Calculate power: first number raised to second number
power() {
  echo $(($1 ** $2))
}

## Check if a number is even
is_even() {
  if (($1 % 2 == 0)); then
    return 0
  else
    return 1
  fi
}

## Check if a number is odd
is_odd() {
  if is_even "$1"; then
    return 1
  else
    return 0
  fi
}

Тепер створіть скрипт, який використовує цю бібліотеку:

touch use_library.sh

Додайте наступний вміст:

#!/bin/bash

## Source the math functions library
source math_functions.lib

## Display a header
echo "Math Functions Demo"
echo "------------------"

## Test the functions
echo "Addition: 5 + 3 = $(add 5 3)"
echo "Subtraction: 10 - 4 = $(subtract 10 4)"
echo "Multiplication: 6 * 7 = $(multiply 6 7)"

## Test division with error handling
div_result=$(divide 20 5)
if [ $? -eq 0 ]; then
  echo "Division: 20 / 5 = $div_result"
else
  echo "Division error: Cannot divide by zero"
fi

## Test division by zero
div_result=$(divide 20 0)
if [ $? -eq 0 ]; then
  echo "Division: 20 / 0 = $div_result"
else
  echo "Division error: Cannot divide by zero"
fi

echo "Power: 2 ^ 8 = $(power 2 8)"

## Test the even/odd functions
echo ""
echo "Number properties:"
for num in 1 2 3 4 5; do
  echo -n "Number $num is "

  if is_even $num; then
    echo "even"
  else
    echo "odd"
  fi
done

Збережіть, зробіть виконуваним файлом та запустіть скрипт:

chmod +x use_library.sh
./use_library.sh

Ви повинні побачити:

Math Functions Demo
------------------
Addition: 5 + 3 = 8
Subtraction: 10 - 4 = 6
Multiplication: 6 * 7 = 42
Division: 20 / 5 = 4.00
Division error: Cannot divide by zero
Power: 2 ^ 8 = 256

Number properties:
Number 1 is odd
Number 2 is even
Number 3 is odd
Number 4 is even
Number 5 is odd

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

Висновок

Ця стаття стала покроковим путівником у світ функцій Bash — від створення найпростішої структури до побудови повноцінних бібліотек багаторазового використання. Ви дізналися, як правильно визначати функції, передавати аргументи, працювати з кодами повернення та повертати власні значення. Матеріал навчив розрізняти, коли використовувати return, а коли echo, як застосовувати локальні змінні для уникнення конфліктів і як організовувати логіку коду у зручні, зрозумілі блоки.

Ви також побачили, як за допомогою функцій можна створювати практичні утиліти, реалізовувати перевірку помилок і підвищувати надійність скриптів. Знання про функції — це основа якісного Bash-програмування. Розуміючи, як вони працюють, ви зможете писати ефективні, гнучкі та легко підтримувані сценарії, що виглядають професійно й стабільно працюють у будь-яких умовах.

Підписатися
Сповістити про
0 Коментарі
Найстаріші
Найновіше Найбільше голосів
Знайшли помилку?
Якщо ви знайшли помилку, зробіть скріншот і надішліть його боту.