1. Funksiyalar va modullik โ
๐ฏ Bu bobda nimani o'rganasiz:
- Funksiyani e'lon qilish, chaqirish va argumentlar uzatish
returnvaechoorqali qiymat qaytarish (ikkalasi farq qiladi!)localo'zgaruvchilar va scope mantig'i- Qayta ishlatiluvchi kutubxonalar yozish (
sourceorqali 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.
# 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 โ
function salomlash() {
echo "Salom!"
}B. POSIX shakli (qavslar bilan) โ
salomlash() {
echo "Salom!"
}Ikkalasi ham ishlaydi. POSIX shakli tavsiya etiladi โ chunki:
- Boshqa POSIX shellarda ham ishlaydi (sh, dash)
- Qisqaroq
functionkalit 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:
salomlash # โ
to'g'ri
salomlash() # โ xato โ sintaksis buzilgan1.3. Birinchi to'liq misol โ
#!/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:
=== 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.
salomlash # โ XATO โ hali e'lon bo'lmagan
salomlash() { echo "Salom"; }
salomlash # โ
to'g'ri1.4. Argumentlar โ
Funksiyaga argumentlar xuddi skriptga argument uzatgandek uzatiladi โ $1, $2, ... orqali.
salomlash() {
echo "Salom, $1!"
echo "Yoshingiz: $2"
}
salomlash "Ali" 25
# Salom, Ali!
# Yoshingiz: 25Asosiy maxsus o'zgaruvchilar โ
| O'zgaruvchi | Mazmuni |
|---|---|
$1, $2, โฆ | Pozitsion argumentlar |
$# | Argumentlar soni |
$@ | Barcha argumentlar (alohida โ har biri o'z elementi) |
$* | Barcha argumentlar (bitta string) |
$0 | Skript nomi (funksiya nomi EMAS โ diqqat!) |
${FUNCNAME[0]} | Joriy funksiya nomi |
$@ va $* farqi
example() {
for arg in "$@"; do echo "@ qoldirdi: $arg"; done
for arg in "$*"; do echo "* qoldirdi: $arg"; done
}
example "salom dunyo" "bash"Natija:
@ qoldirdi: salom dunyo
@ qoldirdi: bash
* qoldirdi: salom dunyo bash # birga qo'shdi!Deyarli har doim "$@" ishlatiladi.
Misol: ikki son yig'indisi โ
yigindi() {
echo $(($1 + $2))
}
yigindi 5 7 # 12
yigindi 100 200 # 3001.5. Default qiymatlar va validatsiya โ
Default qiymat โ ${var:-default} โ
salomlash() {
local ism="${1:-Anonim}"
echo "Salom, $ism!"
}
salomlash "Ali" # Salom, Ali!
salomlash # Salom, Anonim!Majburiy argument โ ${var:?xato xabar} โ
backup() {
local src="${1:?manba katalog ko'rsatilmagan}"
echo "Backup boshlandi: $src"
}
backup # XATO: manba katalog ko'rsatilmagan
backup ~/docs # Backup boshlandi: /Users/mac/docsParameter expansion to'plami
| Sintaksis | Mazmuni |
|---|---|
${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 โ
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).
fayl_bormi() {
[[ -f "$1" ]] && return 0 || return 1
}
if fayl_bormi "/etc/passwd"; then
echo "Mavjud"
fi256 yoki ko'p โ XATO
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.
kvadrat() {
local n="$1"
echo $((n * n))
}
natija=$(kvadrat 5)
echo "5 ning kvadrati: $natija"
# 5 ning kvadrati: 25Ikkalasini birga ishlatish โ
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"
fiStdout 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.
salomlash() {
ism="Ali" # GLOBAL โ funksiyadan tashqarida ham ko'rinadi!
echo "Salom, $ism"
}
ism="Vali"
salomlash
echo "Tashqarida: $ism" # "Ali" โ qayta yozildi!Yechim: local โ
salomlash() {
local ism="Ali" # FAQAT funksiya ichida
echo "Salom, $ism"
}
ism="Vali"
salomlash
echo "Tashqarida: $ism" # "Vali" โ saqlanib qoldiHar doim local ishlating!
Funksiya ichidagi har bir yangi o'zgaruvchi uchun local qo'shing. Bu โ xavfsizlik va izolyatsiya.
local ning nozik tomonlari โ
# 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 โ
readonly MAX_RETRIES=3
readonly LOG_FILE="/var/log/app.log"
MAX_RETRIES=5 # XATO: readonly variableLoyiha-darajadagi konstantalar
Skript boshida readonly o'zgaruvchilarni e'lon qilib qo'ying โ bu kod oqimini belgilab beradi:
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 โ
# 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 โ
#!/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) โ
# 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 โ
| Tavsiya | Misol |
|---|---|
snake_case ishlating | log_info, parse_args |
Ichki funksiyalar _ bilan boshlansin | _private_helper |
| Fe'l + ot | get_user, check_disk |
Boolean โ is_* yoki has_* | is_root, has_internet |
| Modul prefiksi | db_connect, db_close |
To'liq dokumentlangan funksiya namunasi โ
# 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:
# 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:
#!/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_LEVELorqali filtrlashLOG_FILEo'rnatilgan bo'lsa โ faylga ham yozadi- Ranglar terminalga, oddiy matn faylga
- Yagona "guard" โ bir necha marta source qilinmaydi
- Hammasi
localda, scope toza
1.12. Tez-tez uchraydigan xatolar โ
Funksiyalarda klassik tuzoqlar
localunutilgan.bashfn() { x=5; } # x global bo'lib qoladi!localexit code'ni yutadi.bashfn() { local r=$(may_fail); echo $?; } # har doim 0 # To'g'ri: fn() { local r; r=$(may_fail); echo $?; }returnraqamli emas.bashreturn "xato" # XATO โ faqat 0..255Funksiya nomi va o'zgaruvchi nomi to'qnashishi.
bashlog=anything # endi log nomli funksiyani ham buzasiz potentsialFunksiya hali e'lon qilinmagan vaqtda chaqirilgan.
bashfn # โ fn() { ...}echoo'rnigaprintfishlatilmagan.echo -eportativ emas. Format kerak bo'lsaprintfishlating.Stderr ga yozish unutilgan. Xato xabari โ stdout'da emas,
>&2'da bo'lishi kerak.
1.13. Mashqlar โ
๐งช Kelajakda quyidagilar
bashlings watch 06_functionsorqali avto-tekshiriladi. Hozircha qo'l bilan tekshiring.
is_evenfunksiyasini yozing โ son juftmi yoki toqmi (return 0/return 1).repeat_wordfunksiyasi โ birinchi argumentdagi so'zni ikkinchi argumentdagi son marta chiqarsin.max3โ uchta sondan eng kattasini stdout'gaechoqilsin.prompt_confirmโ foydalanuvchidan "Davom etamizmi? [y/N]" so'rab, javobiga ko'ra 0 yoki 1 qaytarsin.lib/math.shmodulini yarating:sum,mul,powfunksiyalari bilan. Asosiy skriptdasourceqiling va sinab ko'ring.
1.14. Xulosa โ
| Tushuncha | Asosiy nuqta |
|---|---|
| E'lon qilish | name() { ... } โ POSIX shakl tavsiya |
| Argumentlar | $1, $@, $# โ har doim "$@" |
| Default qiymat | ${1:-default} |
return | Faqat 0..255 โ exit code |
echo | Haqiqiy qiymat qaytarish uchun |
local | Funksiya ichidagi har o'zgaruvchi uchun majburiy |
readonly | Konstantalar uchun |
source / . | Kutubxonani joriy shellga yuklash |
| Nom konvensiyasi | snake_case, is_*/has_*, modul prefiksi |
| Stderr | Xato xabarlari >&2 ga |
๐ Birinchi capstone yaqinlashdi โ keyingi bobda biz massivlar bilan yanada kuchli funksiyalar yozamiz.
Keyingi sahifa: 2. Massivlar va lug'atlar โ