Skip to content

1. Funksiyalar va modullik โ€‹

๐ŸŽฏ Bu bobda nimani o'rganasiz:

  • Funksiyani e'lon qilish, chaqirish va argumentlar uzatish
  • return va echo orqali qiymat qaytarish (ikkalasi farq qiladi!)
  • local o'zgaruvchilar va scope mantig'i
  • Qayta ishlatiluvchi kutubxonalar yozish (source orqali yuklash)
  • Real misol โ€” kichik logging library

โฑ Vaqt: ~25 daqiqa o'qish + mashqlar ๐Ÿงช Mashqlar: bashlings watch 06_functions (kelajak sprint)


1.1. Nima uchun funksiyalar? โ€‹

Tasavvur qiling โ€” skriptingiz uch joyda bir xil ishni bajaradi: log yozadi, vaqt belgisini qo'yadi, qiziq rang chiqaradi. Har joyda 4 qatordan yozish โ€” DRY (Don't Repeat Yourself) prinsipini buzadi.

Funksiya โ€” bu nomi bor kod bloki. Bir marta yozasiz, ko'p marta chaqirasiz.

bash
# YOMON โ€” uch joyda takror
echo "[$(date +%T)] Backup boshlandi"
# ... ishlar ...
echo "[$(date +%T)] Database eksport qilindi"
# ... ishlar ...
echo "[$(date +%T)] Yakunlandi"

# YAXSHI โ€” funksiya orqali
log() {
    echo "[$(date +%T)] $*"
}

log "Backup boshlandi"
log "Database eksport qilindi"
log "Yakunlandi"

Funksiyaning afzalliklari

  • Qisqalik โ€” kod 3ร— kichrayadi
  • Yagona haqiqat manbai โ€” format'ni o'zgartirish 1 joyda
  • Test qilish oson โ€” har funksiyani alohida sinash mumkin
  • O'qish oson โ€” log "..." o'zi maqsadni aytadi

1.2. E'lon qilish sintaksisi โ€‹

Bashda funksiyani ikki shaklda e'lon qilish mumkin:

A. function kalit so'zi bilan โ€‹

bash
function salomlash() {
    echo "Salom!"
}

B. POSIX shakli (qavslar bilan) โ€‹

bash
salomlash() {
    echo "Salom!"
}

Ikkalasi ham ishlaydi. POSIX shakli tavsiya etiladi โ€” chunki:

  • Boshqa POSIX shellarda ham ishlaydi (sh, dash)
  • Qisqaroq
  • function kalit so'zi keraksiz shovqin

Qavslar bo'sh โ€” argument deyiladi, lekin ishlatilmaydi

salomlash() ichidagi () โ€” funksiya ekanligini bildiradi. Argumentlar bu yerda berilmaydi, ular $1, $2, ... orqali ichkarida ishlatiladi.

Chaqirish โ€‹

Funksiyani nomi bilan chaqirasiz, qavslarsiz:

bash
salomlash           # โœ… to'g'ri
salomlash()         # โŒ xato โ€” sintaksis buzilgan

1.3. Birinchi to'liq misol โ€‹

bash
#!/usr/bin/env bash

# Funksiya e'loni
salomlash() {
    echo "Salom, Bash dunyosi!"
    echo "Bugun: $(date +%F)"
}

# Asosiy mantiq
echo "=== Skript boshlandi ==="
salomlash
echo "=== Skript yakunlandi ==="

Natija:

text
=== Skript boshlandi ===
Salom, Bash dunyosi!
Bugun: 2026-05-16
=== Skript yakunlandi ===

E'lon tartibi muhim!

Funksiyani ishlatishdan oldin e'lon qilish kerak. Bash skriptlarni yuqoridan pastga o'qiydi.

bash
salomlash   # โŒ XATO โ€” hali e'lon bo'lmagan
salomlash() { echo "Salom"; }
salomlash   # โœ… to'g'ri

1.4. Argumentlar โ€‹

Funksiyaga argumentlar xuddi skriptga argument uzatgandek uzatiladi โ€” $1, $2, ... orqali.

bash
salomlash() {
    echo "Salom, $1!"
    echo "Yoshingiz: $2"
}

salomlash "Ali" 25
# Salom, Ali!
# Yoshingiz: 25

Asosiy maxsus o'zgaruvchilar โ€‹

O'zgaruvchiMazmuni
$1, $2, โ€ฆPozitsion argumentlar
$#Argumentlar soni
$@Barcha argumentlar (alohida โ€” har biri o'z elementi)
$*Barcha argumentlar (bitta string)
$0Skript nomi (funksiya nomi EMAS โ€” diqqat!)
${FUNCNAME[0]}Joriy funksiya nomi

$@ va $* farqi

bash
example() {
    for arg in "$@"; do echo "@ qoldirdi: $arg"; done
    for arg in "$*"; do echo "* qoldirdi: $arg"; done
}
example "salom dunyo" "bash"

Natija:

text
@ qoldirdi: salom dunyo
@ qoldirdi: bash
* qoldirdi: salom dunyo bash   # birga qo'shdi!

Deyarli har doim "$@" ishlatiladi.

Misol: ikki son yig'indisi โ€‹

bash
yigindi() {
    echo $(($1 + $2))
}

yigindi 5 7        # 12
yigindi 100 200    # 300

1.5. Default qiymatlar va validatsiya โ€‹

Default qiymat โ€” ${var:-default} โ€‹

bash
salomlash() {
    local ism="${1:-Anonim}"
    echo "Salom, $ism!"
}

salomlash "Ali"     # Salom, Ali!
salomlash           # Salom, Anonim!

Majburiy argument โ€” ${var:?xato xabar} โ€‹

bash
backup() {
    local src="${1:?manba katalog ko'rsatilmagan}"
    echo "Backup boshlandi: $src"
}

backup           # XATO: manba katalog ko'rsatilmagan
backup ~/docs    # Backup boshlandi: /Users/mac/docs

Parameter expansion to'plami

SintaksisMazmuni
${var:-default}Bo'sh bo'lsa default, lekin o'rnatmaydi
${var:=default}Bo'sh bo'lsa default va o'rnatadi
${var:?xabar}Bo'sh bo'lsa xato bilan to'xtatadi
${var:+almashtir}Bo'sh emas bo'lsa almashtirilgan qiymatni qaytaradi

Argumentlarni qo'lda validatsiya โ€‹

bash
backup() {
    if [[ $# -lt 2 ]]; then
        echo "Foydalanish: backup <manba> <maqsad>" >&2
        return 1
    fi

    local src="$1"
    local dst="$2"

    if [[ ! -d "$src" ]]; then
        echo "โŒ Manba topilmadi: $src" >&2
        return 1
    fi

    echo "โœ… $src โ†’ $dst"
}

1.6. Qaytariladigan qiymatlar โ€” return vs echo โ€‹

Bashning eng chalkash jihati โ€” funksiyadan qiymat qaytarish.

return โ€” faqat exit kodi (0..255) โ€‹

return boshqa tillardagi return emas. U faqat exit code qaytaradi: 0 (muvaffaqiyat) yoki 1..255 (xato).

bash
fayl_bormi() {
    [[ -f "$1" ]] && return 0 || return 1
}

if fayl_bormi "/etc/passwd"; then
    echo "Mavjud"
fi

256 yoki ko'p โ€” XATO

bash
qaytar() { return 256; }
qaytar
echo $?   # 0 โ€” wrap around!

echo โ€” haqiqiy qiymat qaytarish โ€‹

Agar real qiymat (son, string) qaytarmoqchi bo'lsangiz โ€” uni echo qiling. Chaqiruvchi $(...) bilan oladi.

bash
kvadrat() {
    local n="$1"
    echo $((n * n))
}

natija=$(kvadrat 5)
echo "5 ning kvadrati: $natija"
# 5 ning kvadrati: 25

Ikkalasini birga ishlatish โ€‹

bash
parse_yosh() {
    local yosh="$1"
    if [[ ! "$yosh" =~ ^[0-9]+$ ]]; then
        echo "noto'g'ri yosh" >&2
        return 1
    fi
    echo "$yosh"
    return 0
}

if y=$(parse_yosh "$1"); then
    echo "โœ… Yosh: $y"
else
    echo "โŒ Parsing xato bo'ldi"
fi

Stdout vs stderr

Funksiya xato xabarini stderr ga (>&2), qaytariladigan qiymatni stdoutga yozsin. Aks holda $(...) xato xabarini ham yutib qoladi.


1.7. Scope: local vs global โ€‹

Default holatda Bashda barcha o'zgaruvchilar global. Bu โ€” xavfli.

bash
salomlash() {
    ism="Ali"          # GLOBAL โ€” funksiyadan tashqarida ham ko'rinadi!
    echo "Salom, $ism"
}

ism="Vali"
salomlash
echo "Tashqarida: $ism"   # "Ali" โ€” qayta yozildi!

Yechim: local โ€‹

bash
salomlash() {
    local ism="Ali"    # FAQAT funksiya ichida
    echo "Salom, $ism"
}

ism="Vali"
salomlash
echo "Tashqarida: $ism"   # "Vali" โ€” saqlanib qoldi

Har doim local ishlating!

Funksiya ichidagi har bir yangi o'zgaruvchi uchun local qo'shing. Bu โ€” xavfsizlik va izolyatsiya.

local ning nozik tomonlari โ€‹

bash
# Bir nechta local qo'shish
fn() {
    local a b c
    local x="bir" y="ikki"
}

# `local` exit code'ni yutib qo'yadi โ€” buggi bo'lishi mumkin
fn() {
    local result=$(maybe_fail)   # โš ๏ธ maybe_fail xato bo'lsa ham $? = 0
}

# To'g'ri yo'l:
fn() {
    local result
    result=$(maybe_fail)         # endi $? to'g'ri
}

1.8. readonly โ€” konstantalar โ€‹

bash
readonly MAX_RETRIES=3
readonly LOG_FILE="/var/log/app.log"

MAX_RETRIES=5   # XATO: readonly variable

Loyiha-darajadagi konstantalar

Skript boshida readonly o'zgaruvchilarni e'lon qilib qo'ying โ€” bu kod oqimini belgilab beradi:

bash
readonly SCRIPT_NAME="$(basename "$0")"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly LOG_FILE="${LOG_FILE:-/tmp/app.log}"

1.9. Funksiyalar kutubxonasi โ€” source โ€‹

Funksiyalarni boshqa faylga ko'chirib, qayta-qayta ishlatish mumkin.

lib/log.sh โ€” qayta ishlatiluvchi modul โ€‹

bash
# lib/log.sh

log_info()  { printf '\033[32m[INFO]\033[0m  %s\n' "$*"; }
log_warn()  { printf '\033[33m[WARN]\033[0m  %s\n' "$*" >&2; }
log_error() { printf '\033[31m[ERROR]\033[0m %s\n' "$*" >&2; }

die() {
    log_error "$*"
    exit 1
}

Asosiy skript: main.sh โ€‹

bash
#!/usr/bin/env bash
set -euo pipefail

# Modulni yuklash โ€” ikki yo'l mavjud:
source "$(dirname "$0")/lib/log.sh"
# yoki qisqa:
. "$(dirname "$0")/lib/log.sh"

log_info "Skript ishga tushdi"
log_warn "Disk hajmi past"
log_error "Database ulanishi yo'q"
die "Kritik xato โ€” to'xtatamiz"

source qachon bash dan farq qiladi?

  • bash script.sh โ†’ yangi subshell ochiladi. Funksiyalar tashqariga chiqmaydi.
  • source script.sh โ†’ joriy shellda ishlaydi. Funksiyalar yuklanadi.

Kutubxona uchun har doim source (yoki .) ishlating.

Idiomatic โ€” modulni faqat bir marta yuklash (guard) โ€‹

bash
# lib/log.sh boshida
[[ -n "${__LOG_LOADED:-}" ]] && return 0
readonly __LOG_LOADED=1

log_info() { ... }
# ...

C/C++'dagi #ifndef GUARD ekvivalenti.


1.10. Nom konvensiyalari va best practice โ€‹

TavsiyaMisol
snake_case ishlatinglog_info, parse_args
Ichki funksiyalar _ bilan boshlansin_private_helper
Fe'l + otget_user, check_disk
Boolean โ€” is_* yoki has_*is_root, has_internet
Modul prefiksidb_connect, db_close

To'liq dokumentlangan funksiya namunasi โ€‹

bash
# Foydalanuvchi root ekanligini tekshiradi.
#
# Argumentlar:
#   yo'q
# Qaytaradi:
#   0 โ€” root
#   1 โ€” boshqa foydalanuvchi
# Misol:
#   if is_root; then ...
is_root() {
    [[ $EUID -eq 0 ]]
}

1.11. Real misol โ€” Logging library โ€‹

To'liq qayta ishlatiluvchi modul:

bash
# lib/logger.sh
#
# Foydalanish:
#   source lib/logger.sh
#   log_info "Boshlandi"
#   log_warn "Disk past"
#   log_error "Xato"
#   LOG_LEVEL=debug log_debug "Detal"

[[ -n "${__LOGGER_LOADED:-}" ]] && return 0
readonly __LOGGER_LOADED=1

# Konfiguratsiya (foydalanuvchi override qilishi mumkin)
LOG_LEVEL="${LOG_LEVEL:-info}"
LOG_FILE="${LOG_FILE:-}"

readonly __LOG_RED='\033[31m'
readonly __LOG_YELLOW='\033[33m'
readonly __LOG_GREEN='\033[32m'
readonly __LOG_BLUE='\033[34m'
readonly __LOG_RESET='\033[0m'

# Daraja raqamlari
declare -A __LOG_LEVELS=(
    [debug]=0 [info]=1 [warn]=2 [error]=3
)

_log() {
    local level="$1"; shift
    local color="$1"; shift
    local msg="$*"

    # Daraja filtrlash
    local req="${__LOG_LEVELS[$level]:-1}"
    local cur="${__LOG_LEVELS[$LOG_LEVEL]:-1}"
    (( req < cur )) && return 0

    local ts
    ts=$(date '+%Y-%m-%d %H:%M:%S')
    local line
    line=$(printf '[%s] [%-5s] %s' "$ts" "${level^^}" "$msg")

    printf '%b%s%b\n' "$color" "$line" "$__LOG_RESET" >&2
    [[ -n "$LOG_FILE" ]] && printf '%s\n' "$line" >> "$LOG_FILE"
}

log_debug() { _log debug "$__LOG_BLUE"   "$@"; }
log_info()  { _log info  "$__LOG_GREEN"  "$@"; }
log_warn()  { _log warn  "$__LOG_YELLOW" "$@"; }
log_error() { _log error "$__LOG_RED"    "$@"; }

die() {
    log_error "$@"
    exit 1
}

Ishlatish:

bash
#!/usr/bin/env bash
set -euo pipefail
source ./lib/logger.sh

LOG_FILE=/tmp/app.log
log_info "Boshlandi"
log_warn "Disk 80% to'lgan"
log_error "Database javob bermayapti"

[[ -f /etc/critical ]] || die "Kritik fayl yo'q"

Bu lib nima qiladi?

  • 4 ta daraja: debug/info/warn/error
  • LOG_LEVEL orqali filtrlash
  • LOG_FILE o'rnatilgan bo'lsa โ€” faylga ham yozadi
  • Ranglar terminalga, oddiy matn faylga
  • Yagona "guard" โ€” bir necha marta source qilinmaydi
  • Hammasi local da, scope toza

1.12. Tez-tez uchraydigan xatolar โ€‹

Funksiyalarda klassik tuzoqlar

  1. local unutilgan.

    bash
    fn() { x=5; }   # x global bo'lib qoladi!
  2. local exit code'ni yutadi.

    bash
    fn() { local r=$(may_fail); echo $?; }   # har doim 0
    # To'g'ri:
    fn() { local r; r=$(may_fail); echo $?; }
  3. return raqamli emas.

    bash
    return "xato"      # XATO โ€” faqat 0..255
  4. Funksiya nomi va o'zgaruvchi nomi to'qnashishi.

    bash
    log=anything       # endi log nomli funksiyani ham buzasiz potentsial
  5. Funksiya hali e'lon qilinmagan vaqtda chaqirilgan.

    bash
    fn          # โŒ
    fn() { ...}
  6. echo o'rniga printf ishlatilmagan.echo -e portativ emas. Format kerak bo'lsa printf ishlating.

  7. Stderr ga yozish unutilgan. Xato xabari โ€” stdout'da emas, >&2'da bo'lishi kerak.


1.13. Mashqlar โ€‹

๐Ÿงช Kelajakda quyidagilar bashlings watch 06_functions orqali avto-tekshiriladi. Hozircha qo'l bilan tekshiring.

  1. is_even funksiyasini yozing โ€” son juftmi yoki toqmi (return 0 / return 1).
  2. repeat_word funksiyasi โ€” birinchi argumentdagi so'zni ikkinchi argumentdagi son marta chiqarsin.
  3. max3 โ€” uchta sondan eng kattasini stdout'ga echo qilsin.
  4. prompt_confirm โ€” foydalanuvchidan "Davom etamizmi? [y/N]" so'rab, javobiga ko'ra 0 yoki 1 qaytarsin.
  5. lib/math.sh modulini yarating: sum, mul, pow funksiyalari bilan. Asosiy skriptda source qiling va sinab ko'ring.

1.14. Xulosa โ€‹

TushunchaAsosiy nuqta
E'lon qilishname() { ... } โ€” POSIX shakl tavsiya
Argumentlar$1, $@, $# โ€” har doim "$@"
Default qiymat${1:-default}
returnFaqat 0..255 โ€” exit code
echoHaqiqiy qiymat qaytarish uchun
localFunksiya ichidagi har o'zgaruvchi uchun majburiy
readonlyKonstantalar uchun
source / .Kutubxonani joriy shellga yuklash
Nom konvensiyasisnake_case, is_*/has_*, modul prefiksi
StderrXato xabarlari >&2 ga

๐ŸŽ‰ Birinchi capstone yaqinlashdi โ€” keyingi bobda biz massivlar bilan yanada kuchli funksiyalar yozamiz.

Keyingi sahifa: 2. Massivlar va lug'atlar โ†’

MIT litsenziyasi asosida tarqatiladi.