O'zgaruvchilar va argumentlar
Bash skript asoslari maqolasidagi hello.sh skripti har doim bir xil, qattiq yozilgan (hardcoded) xabarni chiqarardi. Real vazifada esa skript har safar turli ma’lumotlar bilan ishlashi kerak — boshqa fayl nomi, boshqa foydalanuvchi, boshqa sana. Buni ikki mexanizm hal qiladi: ma’lumotni skript ichida saqlaydigan o'zgaruvchilar (variables) va ma’lumotni skriptga tashqaridan, buyruq qatoridan uzatadigan argumentlar. Bu maqola ikkalasini ham ko'rib chiqadi.
Nimalarni o'rganasiz
Bu maqola oxirida siz quyidagilarni qila olasiz:
- o'zgaruvchini e’lon qilish va ishlatish qoidalariga amal qilish;
${VAR}sintaksisi qachon majburiy ekanini tushuntirish;- buyruq chiqishini o'zgaruvchiga olish (command substitution);
- skriptga positional parametrlar (
$1,$2,$@,$#) orqali argument uzatish; readyordamida foydalanuvchidan interaktiv kiritish qabul qilish;- qo'shtirnoq (quoting) nega muhimligini tushuntirish.
O'zgaruvchini e’lon qilish va ishlatish
O'zgaruvchi — nom va qiymatdan iborat saqlash joyi. Bash’da o'zgaruvchiga qiymat berish sintaksisi quyidagicha:
Bu yerda ikki qoida qat’iy: tenglik belgisidan oldin ham, keyin ham bo'sh joy bo'lmasligi kerak. MY_SHELL = "bash" (bo'sh joylar bilan) xato beradi, chunki Bash bu holda MY_SHELLni buyruq nomi, = va "bash"ni esa uning argumentlari sifatida talqin qilishga urinadi.
O'zgaruvchidan foydalanish uchun nom oldiga $ qo'yiladi:
Odatga ko'ra o'zgaruvchi nomlari katta harflarda yoziladi, lekin bu majburiy emas — kichik harfli o'zgaruvchi ham aynan shunday ishlaydi. Muhimi — o'z skriptlaringizda bir xil uslubga amal qilish.
O'zgaruvchi nomida harflar, raqamlar va pastki chiziq (_) bo'lishi mumkin, lekin u raqam bilan boshlanmasligi kerak:
# Correct
user_1="ali"
_TEMP="/tmp/data"
# Incorrect — starts with a digit
1user="ali"
# Incorrect — disallowed characters (-, @)
user-name="ali"
user@host="srv"
Jingalak qavs sintaksisi: ${VAR}
Quyidagi vaziyatni ko'rib chiqaylik:
Bu yerda bashing chiqishini kutish mumkin, lekin natija bo'sh. Sababi — Bash $MY_SHELLingni bitta butun o'zgaruvchi nomi sifatida o'qishga urinadi, bunday nomli o'zgaruvchi esa mavjud emas. Muammoni jingalak qavslar hal qiladi:
${ } o'zgaruvchi nomining aniq chegarasini belgilaydi. Uni har doim ishlatish mumkin, lekin u faqat o'zgaruvchidan keyin yoki oldin darhol boshqa matn kelganda majburiy. Boshqa barcha holatlarda $VAR va ${VAR} bir xil ishlaydi.
Buyruq chiqishini o'zgaruvchiga olish
Buyruq chiqishini o'zgaruvchida saqlash uchun command substitution ishlatiladi:
Avval $( ) ichidagi buyruq bajariladi va uning standart chiqishi (stdout) o'zgaruvchining qiymatiga aylanadi. Eski skriptlarda xuddi shu maqsadda ba’zan backtick’lar ishlatiladi:
Ikkala shakl bir xil natija beradi, lekin backtick sintaksisi eskirgan hisoblanadi: uni ichma-ich ishlatish noqulay va o'qish qiyinroq. Yangi skriptlarda faqat $( ) shaklidan foydalanish kerak.
Qo'shtirnoq ichida o'zgaruvchini kengaytirish
O'zgaruvchi qo'sh qo'shtirnoq ("...") ichida ham kengayadi (expand bo'ladi):
Bittalik qo'shtirnoq ('...') ichida esa hech narsa kengaymaydi — $NAME aynan yozilganicha, belgima-belgi chiqariladi:
Tip
Amaliy qoida: o'zgaruvchini har doim qo'sh qo'shtirnoq ichida ishlating ("$VAR"), ayniqsa u fayl yo'li yoki foydalanuvchi kiritgan matn bo'lsa. Qo'shtirnoqsiz holatda $VAR qiymatida bo'sh joy bo'lsa, Bash uni bir nechta alohida so'zga ajratib yuborishi mumkin. Masalan, rm $FILE kabi buyruqda bu nomida bo'sh joy bor faylni noto'g'ri talqin qilib, kutilmagan fayllarni o'chirib yuborishi mumkin. rm "$FILE" aynan shu xatodan himoya qiladi.
Positional parametrlar: skriptga argument uzatish
Skript ishga tushirilayotganda buyruq qatoridan qiymatlar uzatish mumkin. Ular positional parametrlar deb ataladi va $0 dan $9 gacha bo'lgan maxsus o'zgaruvchilarda saqlanadi:
$0— skriptning o'zi (u chaqirilgan yo'l);$1— birinchi argument;$2— ikkinchi argument va hokazo.
Bu chaqiruvda $0 — ./script.sh, $1 — parameter1, $2 — parameter2, $3 esa parameter3.
Amaliy misol — foydalanuvchi nomini argument sifatida qabul qiladigan archive_user.sh skripti:
#!/bin/bash
# Archives a user's home directory
# Usage: ./archive_user.sh <username>
user="$1"
tar -czf "/backup/${user}.tar.gz" "/home/${user}"
echo "Archived: /backup/${user}.tar.gz"
E’tibor bering: $1 qiymati o'qilishi bilanoq u mazmunli nomli o'zgaruvchida (user) saqlanadi. Bu skriptning qolgan qismini o'qishni ancha osonlashtiradi, chunki keyingi qatorlarda $1 o'rniga ma’nosi darhol tushunarli bo'lgan $user ishlatiladi.
Barcha argumentlar bilan ishlash: $@ va $#
Agar skript nechta argument olishini oldindan bilmasa, ularning hammasini birma-bir aylanib chiqishi kerak. Buning uchun ikkita maxsus o'zgaruvchi bor:
$@— barcha positional parametrlarni ($1 dan boshlab) alohida so'zlar sifatida beradi;$#— argumentlar sonini beradi.
#!/bin/bash
echo "Total number of arguments: $#"
for user in "$@"; do
echo "Archiving: $user"
tar -czf "/backup/${user}.tar.gz" "/home/${user}"
done
for sikli Shartlar va sikllar maqolasida batafsil ko'rib chiqiladi. Bu yerdagi asosiy qoida shuki, "$@" har doim qo'sh qo'shtirnoq ichida ishlatiladi ($@ emas, "$@"). Faqat shunda ichida bo'sh joy bor argument (masalan, "ali vali") ikkiga bo'linib ketmasdan, bitta butun element sifatida saqlanib qoladi.
Note
Agar argumentlar berilmagan bo'lsa (masalan, $1 umuman uzatilmagan bo'lsa-yu, u ishlatilsa), skript bo'sh qiymat bilan davom etadi. Bu ko'pincha kutilmagan xatolarga olib keladi. Argumentlar sonini tekshirish Exit kodlar va xatolarni qayta ishlash maqolasida ko'rib chiqiladi.
"$@" va "$*": muhim farq
Bash’da barcha argumentlarni beradigan ikkinchi o'zgaruvchi ham bor — $*. Ikkalasi orasidagi farq, ayniqsa qo'shtirnoq ichida, Bash bo'yicha eng ko'p beriladigan intervyu savollaridan biri. Chunki uni noto'g'ri tushunish argumentlarni qayta ishlashni sezdirmasdan buzadi.
"$@"har bir argumentni alohida qo'shtirnoqli so'z sifatida kengaytiradi:"$1" "$2" "$3"."$*"barcha argumentlarniIFSning birinchi belgisi (standart holatda bo'sh joy) bilan ajratib, bitta so'zga birlashtiradi:"$1 $2 $3".
#!/bin/bash
# called as: ./demo.sh "ali vali" bob
printf 'with @: [%s]\n' "$@"
printf 'with *: [%s]\n' "$*"
"$@" ikkita argumentni saqlab qoldi ("ali vali" ichidagi bo'sh joy ham buzilmadi), shuning uchun printf ikki marta ishladi. "$*" esa hammasini bitta satrga yig'di, shuning uchun printf bir marta ishladi. Amaliy qoida: deyarli har doim "$@" dan foydalaning — skript argumentlarini boshqa buyruqqa to'g'ri uzatadigan aynan shu (some_tool "$@"). "$*" ni faqat argumentlarni ataylab bitta birlashtirilgan satr sifatida olmoqchi bo'lganingizda ishlating (masalan, log xabarini tuzishda). Qo'shtirnoqsiz $@ va $* bir xil ishlaydi va bo'sh joylar bo'yicha qayta bo'linadi — qo'shtirnoq aynan shu word splitting xatosining oldini olish uchun mavjud.
shift: argumentlarni bittadan olish
shift $1 ni tashlab yuboradi va qolganlarini bir pog'ona pastga qayta raqamlaydi ($2 $1 ga aylanadi va hokazo), $# ni esa bittaga kamaytiradi. Bu uzunligi o'zgaruvchan argumentlar ro'yxatini qayta ishlashning standart usuli. U, ayniqsa, birinchi argument subcommand yoki option bo'lib, qolganlari uning nishonlari bo'lganda qo'l keladi:
#!/bin/bash
action="$1" # e.g. "delete"
shift # drop the action; "$@" is now just the remaining files
for file in "$@"; do
echo "$action -> $file"
done
shift N birinchi N ta argumentni birdaniga tashlab yuboradi. Argument qolmaganda shift chaqirilsa, Bash’da hech narsa sodir bo'lmaydi (u noldan farqli kod qaytaradi, lekin xato bermaydi). Buni set -e ishlatilganda bilib qo'yish foydali.
Foydalanuvchidan interaktiv kiritish qabul qilish: read
Ba’zan skript ishlayotgan paytda foydalanuvchidan to'g'ridan-to'g'ri ma’lumot so'rashi kerak bo'ladi, masalan, argument berilmagan bo'lsa. Buning uchun read buyrug'i ishlatiladi:
#!/bin/bash
read -p "Enter the username: " user
tar -czf "/backup/${user}.tar.gz" "/home/${user}"
echo "Archived: /backup/${user}.tar.gz"
-p flag'i so'rov (prompt) xabarini ko'rsatadi, undan keyingi so'z esa kiritilgan qiymat yoziladigan o'zgaruvchi nomi. read standart kirishdan (stdin) o'qiydi. Bu odatda klaviatura, lekin pipeline orqali boshqa buyruqning chiqishi ham bo'lishi mumkin, masalan echo "mitch" | read -p "..." user. Bu holatda subshell qanday ishlashi sababli ehtiyot bo'lish kerak: read pipeline ichida ishlaganda o'zgaruvchi asosiy shell’ga o'tmaydi.
Amaliy vaziyat: argument berilmaganda read orqali so'rash
Vazifa: archive_user.sh argument bilan ham, argumentsiz ham ishlasin — agar $1 berilmagan bo'lsa, uni foydalanuvchidan so'rasin.
#!/bin/bash
# Archives a user's home directory.
# Uses the argument if given, otherwise asks interactively.
if [ -z "$1" ]; then
read -p "Enter the username: " user
else
user="$1"
fi
tar -czf "/backup/${user}.tar.gz" "/home/${user}"
echo "Archived: /backup/${user}.tar.gz"
[ -z "$1" ] testi $1 bo'sh bo'lsa (yoki umuman berilmagan bo'lsa) true qaytaradi. Bu test va if sintaksisi Shartlar va sikllar maqolasida to'liq tushuntiriladi. Bu yerda muhimi — bitta skript ham argumentni, ham interaktiv kiritishni qo'llab-quvvatlay olishini ko'rish.
Keng tarqalgan xatolar
Tenglik belgisi atrofida bo'sh joy qoldirish
Bash buni NAME nomli buyruqni = va "ali" argumentlari bilan chaqirish deb tushunadi. To'g'ri shakli: NAME="ali".
O'zgaruvchini qo'shtirnoqsiz ishlatish
Bu ikkita alohida argument (report va 2026.txt) sifatida talqin qilinadi va rm mo'ljallangan bitta faylni emas, ikkalasini (agar mavjud bo'lsa) o'chirishga urinadi. To'g'risi: rm "$FILE".
${VAR} o'rniga $VAR ishlatib, matnni o'zgaruvchi nomiga qo'shib yuborish
Yuqoridagi $MY_SHELLing misoli. Bu xato, ayniqsa, fayl kengaytmasi yoki prefiks qo'shilganda ko'p uchraydi. Masalan, $name_backup.tar.gz deb yozilsa, Bash name_backup nomli o'zgaruvchini qidiradi.
Argumentlar sonini tekshirmasdan $1 ga tayanish
Agar skript $1 argumentiga tayansa-yu, u berilmagan bo'lsa, o'zgaruvchi bo'sh satrga aylanadi va keyingi buyruqlar (masalan, tar yoki rm) bo'sh yoki noto'g'ri yo'l bilan ishga tushishi mumkin. Buni oldindan tekshirish Exit kodlar va xatolarni qayta ishlash maqolasida ko'rib chiqiladi.
Mashqlar
$1orqali ism qabul qilib,"Hello, <name>!"chiqaradigangreet.shskriptini yozing. Argument berilmagan holatniread -pbilan qamrab oling.hostname,whoamivadatechiqishini command substitution orqali uchta alohida o'zgaruvchiga saqlab, ularni bitta qatorda chiqaradigansysinfo.shskriptini yozing.- Ichida bo'sh joy bor argument bilan sinab ko'ring (masalan,
./greet.sh "Ali Vali"): avval$1ni qo'shtirnoqsiz, keyin qo'shtirnoq bilan ishlating va natijadagi farqni tushuntiring. $#orqali argumentlar sonini chiqaradigan, keyin"$@"orqali har birini alohida qatorda ko'rsatadiganlist_args.shskriptini yozing.
Xulosa
O'zgaruvchilar ma’lumotni skript ichida saqlaydi, positional parametrlar ($1, $@, $#) esa ma’lumotni tashqaridan qabul qilish imkonini beradi. read esa foydalanuvchidan ma’lumotni to'g'ridan-to'g'ri so'raydi. Qo'shtirnoq qoidalariga amal qilish, ayniqsa fayl yo'llari bilan ishlaganda, xavfsiz skript yozishning zaruriy qismi. Keyingi mavzu, Shartlar va sikllar, shu o'zgaruvchilar asosida qaror qabul qilish (if) va amallarni takrorlashni (for, while) ko'rib chiqadi.