Shartlar va tsikllar — if, test, for, while, case

~18 daq · Linux · Bash skriptlar

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, -lt yoki (( )).

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 — case teskari

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, $FAYL aynan *.log matni 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 -lt yoki (( a > b ))
  • Fayllar: -f, -d, -e, -s; inkor — !; &&, ||
  • case "$x" in a) ...;; *) ...;; esac
  • for 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 < fayl
  • break, continue

Keyingi dars

39-dars: Funksiyalar, argumentlar va xatolarni boshqarish — set -euo