Shartlar va tsikllar — if, test, for, while, case
Muammodan boshlaylik
Skript qaror qabul qilishi kerak:
- Zaxira papkasi mavjud bo'lmasa — yaratish
- Disk 90% dan to'la bo'lsa — ogohlantirish
- Argument berilmagan bo'lsa — qanday ishlatishni ko'rsatish
- 10 ta serverning har birida bir xil buyruq
Bularning hammasi — shartlar (if, case) va tsikllar (for, while).
if — shart
if SHART; then
buyruqlar
elif BOSHQA_SHART; then
buyruqlar
else
buyruqlar
fi
fi — if teskari yozilgan; blok oxiri.
Shart — bu buyruq
Bash da shart — buyruqning chiqish kodi (3-dars): 0 — rost, boshqa — yolg'on.
if grep -q "ERROR" app.log; then
echo "Logda xatolar bor"
fi
if ping -c 1 -W 2 google.com > /dev/null 2>&1; then
echo "Internet bor"
fi
if systemctl is-active --quiet nginx; then
echo "Nginx ishlayapti"
fi
grep -q — jim (faqat chiqish kodi).
[[ ]] — test
Taqqoslashlar uchun — [[ ... ]]:
if [[ "$1" == "production" ]]; then
echo "Diqqat: production!"
fi
[!WARNING]
[[dan keyin va]]dan oldin bo'shliq majburiy:[["$a"=="b"]]— xato. To'g'ri:[[ "$a" == "b" ]].
[ ... ] (bitta qavs) — eski POSIX shakl, sh da ishlaydi. Bash da [[ ]] xavfsizroq va qulayroq.
Satrlar
| Test | Rost bo'ladi, agar |
|---|---|
[[ "$a" == "$b" ]] |
Teng |
[[ "$a" != "$b" ]] |
Teng emas |
[[ -z "$a" ]] |
Bo'sh (zero) |
[[ -n "$a" ]] |
Bo'sh emas |
[[ "$a" == *.js ]] |
Naqshga mos (glob) |
[[ "$a" =~ ^[0-9]+$ ]] |
Regex ga mos |
Sonlar
| Test | Ma'nosi |
|---|---|
-eq |
teng (=) |
-ne |
teng emas (≠) |
-gt / -ge |
katta / katta yoki teng |
-lt / -le |
kichik / kichik yoki teng |
if [[ $DISK -gt 90 ]]; then ...
if (( DISK > 90 )); then ... # arifmetik shakl — o'qish osonroq
[!INFO]
[[ ]]ichida>va<— satr taqqoslash (alifbo bo'yicha)! Sonlar uchun-gt,-ltyoki(( )).
Fayllar
| Test | Rost bo'ladi, agar |
|---|---|
-e fayl |
Mavjud (har qanday tur) |
-f fayl |
Oddiy fayl |
-d papka |
Papka |
-s fayl |
Mavjud va bo'sh emas |
-r / -w / -x |
O'qish / yozish / bajarish mumkin |
-L fayl |
Symlink |
if [[ ! -d "$ZAXIRA" ]]; then
mkdir -p "$ZAXIRA"
fi
if [[ -f .env ]]; then
set -a; source .env; set +a
fi
! — inkor.
Mantiqiy operatorlar
if [[ -f "$FAYL" && -s "$FAYL" ]]; then ... # VA
if [[ "$1" == "-h" || "$1" == "--help" ]]; then ... # YOKI
Qisqa shakl
[[ -d "$PAPKA" ]] || mkdir -p "$PAPKA"
[[ $# -eq 0 ]] && { echo "Foydalanish: $0 <muhit>"; exit 1; }
Amaliy misol: disk tekshiruvi
#!/bin/bash
CHEGARA=90
FOIZ=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if (( FOIZ >= CHEGARA )); then
echo "⚠️ Disk ${FOIZ}% to'la! Chegara: ${CHEGARA}%"
exit 1
elif (( FOIZ >= 75 )); then
echo "Disk ${FOIZ}% — kuzatib boring"
else
echo "✓ Disk ${FOIZ}% — normal"
fi
case — ko'p tanlov
Ko'p elif o'rniga:
case "$1" in
start)
sudo systemctl start dokon
;;
stop)
sudo systemctl stop dokon
;;
restart|reload)
sudo systemctl restart dokon
;;
status)
systemctl status dokon
;;
*)
echo "Foydalanish: $0 {start|stop|restart|status}"
exit 1
;;
esac
;;— har bir variant oxiri|— bir nechta qiymat*)— boshqa hamma narsa (default)esac—caseteskari
for — ro'yxat bo'yicha
for MEVA in olma nok uzum; do
echo "Meva: $MEVA"
done
Fayllar bo'yicha
for FAYL in *.log; do
echo "Siqilmoqda: $FAYL"
gzip "$FAYL"
done
[!WARNING]
for f in $(ls *.log)— yozmang: bo'shliqli nomlarda buziladi. To'g'ridan-to'g'ri glob:for f in *.log. Mos fayl bo'lmasa,$FAYLaynan*.logmatni bo'ladi — tekshirish:[[ -e "$FAYL" ]] || continue.
Raqamlar
for i in {1..5}; do echo "Urinish $i"; done
for i in $(seq 1 2 10); do echo $i; done # 1 3 5 7 9
for (( i = 0; i < 5; i++ )); do echo $i; done # C uslubi
Serverlar bo'yicha
SERVERLAR=(web1 web2 web3)
for S in "${SERVERLAR[@]}"; do
echo "== $S =="
ssh "$S" "uptime"
done
(...) — massiv; "${MASSIV[@]}" — barcha elementlar.
Argumentlar bo'yicha
for ARG in "$@"; do
echo "Argument: $ARG"
done
while — shart rost ekan
SANOQ=1
while (( SANOQ <= 5 )); do
echo "Qadam $SANOQ"
(( SANOQ++ ))
done
Kutish — eng tipik foydalanish
Ilova ishga tushguncha kutish:
echo -n "Ilova kutilmoqda"
URINISH=0
until curl -sf localhost:3000/health > /dev/null; do
(( URINISH++ ))
if (( URINISH >= 30 )); then
echo " ✗ 30 soniyada ishga tushmadi"
exit 1
fi
echo -n "."
sleep 1
done
echo " ✓"
until — while ning teskarisi: shart yolg'on ekan takrorlaydi.
Faylni qatorma-qator o'qish
while IFS= read -r QATOR; do
echo "Qator: $QATOR"
done < serverlar.txt
IFS= read -r — bo'shliq va \ larni buzmasdan o'qishning to'g'ri shakli. Yodlab oling.
# CSV
while IFS=',' read -r SANA SHAHAR MAHSULOT SONI; do
echo "$SHAHAR: $SONI ta $MAHSULOT"
done < <(tail -n +2 sotuvlar.csv)
< <(buyruq) — buyruq chiqishini fayl kabi o'qish.
break va continue
for F in *.log; do
[[ -s "$F" ]] || continue # bo'sh faylni o'tkazib yuborish
if grep -q "FATAL" "$F"; then
echo "FATAL topildi: $F"
break # tsikldan chiqish
fi
done
Nima uchun shunday?
Nima uchun bash da shart — buyruqning chiqish kodi, boshqa tillardagidek true/false qiymat emas?
Chunki bash ning asosiy vazifasi — buyruqlarni boshqarish, va har bir UNIX buyrug'i allaqachon "muvaffaqiyat yoki xato" ni chiqish kodi orqali bildiradi. if grep -q ... — "grep topdimi?" degan savol tabiiy shart bo'ladi, qo'shimcha o'zgaruvchilarsiz. [[ ]] ham aslida buyruq — u shunchaki taqqoslab, 0 yoki 1 qaytaradi. Bu yagona model: har qanday dastur — Python skripti, curl, docker — shart sifatida ishlatilishi mumkin, agar u chiqish kodini to'g'ri qaytarsa. Shuning uchun o'z dasturlaringizda ham xatoda exit 1 (yoki process.exit(1)) qaytarish muhim.
Xulosa
Eslab qoling:
if ...; then ... elif ...; else ... fi; shart — chiqish kodi[[ ]]— ichida bo'shliqlar;==,!=,-z,-n,=~- Sonlar:
-eq -ne -gt -ltyoki(( a > b )) - Fayllar:
-f,-d,-e,-s; inkor —!;&&,|| case "$x" in a) ...;; *) ...;; esacfor f in *.log,for i in {1..5},for s in "${arr[@]}"while,until— kutish tsikllari (urinishlar chegarasi bilan)while IFS= read -r qator; do ...; done < faylbreak,continue
Keyingi dars
39-dars: Funksiyalar, argumentlar va xatolarni boshqarish — set -euo