در بخش قبل، با ساختار اولیهٔ اسکریپتهای Bash آشنا شدید. اکنون نوبت به یکی از اساسیترین مفاهیم هر زبان برنامهنویسی میرسد: متغیرها و انواع داده. در Bash، همه چیز در ابتدا رشته (string) است، اما میتوان اعداد را بهصورت ریاضی پردازش کرد و حتی آرایههایی با ایندکس عددی یا کلیدی (associative) تعریف نمود. درک درست از متغیرها، پایهٔ نوشتن اسکریپتهای پویا و کارآمد است.
متغیرها در Bash
متغیرها در Bash، مکانهایی در حافظه هستند که به آنها یک نام اختصاصی داده میشود و میتوان مقداری را در آنها ذخیره و بعداً بازیابی کرد.
قوانین نامگذاری متغیرها
-
نام متغیر میتواند شامل حروف بزرگ و کوچک انگلیسی، اعداد و زیرخط (
_) باشد. -
نام متغیر باید با یک حرف یا زیرخط شروع شود؛ نمیتواند با عدد شروع شود.
-
نام متغیرها به حروف بزرگ و کوچک حساس (case-sensitive) هستند؛ بنابراین
myvarوMyVarدو متغیر متفاوت محسوب میشوند. -
استفاده از کاراکترهای خاص مانند
-،*،?و ... در نام متغیر مجاز نیست.
تعریف و مقداردهی
برای تعریف یک متغیر، کافی است نام آن را بنویسید و با علامت مساوی (=) مقداری به آن بدهید. فاصلهٔ سفید (space) قبل و بعد از علامت مساوی نباید وجود داشته باشد.
name="Ali" # درست age=30 # درست user_name="Reza" # درست my-var="bad" # غلط (خط تیره مجاز نیست) var = "value" # غلط (فضای سفید اضافی)
نکته: Bash یک زبان با نوعدهی پویا (dynamically typed) است. یعنی شما نیازی به اعلام نوع متغیر ندارید و میتوانید در هر زمان هر نوع دادهای را به آن نسبت دهید. اما در عمل، همه چیز بهصورت رشته ذخیره میشود.
خواندن مقدار متغیر
برای خواندن مقدار ذخیرهشده در یک متغیر، از علامت $ قبل از نام متغیر استفاده میکنیم.
name="Sara" echo $name # خروجی: Sara echo "سلام $name" # خروجی: سلام Sara
برای جلوگیری از تداخل نام متغیر با متن اطراف، میتوانید آن را در آکولاد ({}) قرار دهید:
lang="bash" echo "من ${lang}را دوست دارم" # خروجی: من bashرا دوست دارم echo "من $langرا دوست دارم" # این نیز کار میکند اما {} خوانایی را بالا میبرد
متغیرهای فقط خواندنی (readonly)
برای اینکه مقدار یک متغیر قابل تغییر نباشد، از دستور readonly استفاده کنید:
readonly PI=3.14 PI=3.15 # خطا: PI readonly است
حذف متغیر
با دستور unset میتوانید یک متغیر را از حافظه حذف کنید:
temp="temp value" unset temp echo $temp # خروجی خالی
متغیرهای محیطی (Environment Variables)
متغیرهای محیطی، متغیرهایی هستند که در سطح فرآیند (process) و تمام فرزندان آن قابل دسترسی هستند. این متغیرها معمولاً برای پیکربندی محیط کاربر، مسیرهای جستجو، تنظیمات زبان و ... استفاده میشوند.
مشاهدهٔ متغیرهای محیطی
برای دیدن همهٔ متغیرهای محیطی فعلی، از دستور env یا printenv استفاده کنید:
env
برای دیدن مقدار یک متغیر محیطی خاص:
echo $HOME # مسیر خانهٔ کاربر echo $PATH # لیست مسیرهای جستجوی دستورات echo $USER # نام کاربر فعلی echo $PWD # مسیر دایرکتوری جاری
تفاوت متغیرهای عادی و محیطی
| نوع متغیر | تعریف | دسترسی در زیر-فرآیندها | مثال |
|---|---|---|---|
| متغیر محلی | با name=value | خیر | myvar="hello" |
| متغیر محیطی | با export name=value | بله | export PATH="/usr/bin:$PATH" |
برای روشن شدن تفاوت، به این مثال توجه کنید:
# تعریف یک متغیر محلی local_var="من محلی هستم" # تعریف یک متغیر محیطی export env_var="من محیطی هستم" # اجرای یک زیر-شل با bash bash -c 'echo $local_var; echo $env_var'
خروجی:
(خالی) من محیطی هستم
متغیر محلی در زیر-شل دیده نمیشود، اما متغیر محیطی به ارث میرسد.
دستور export
دستور export، متغیری را به متغیر محیطی تبدیل میکند و آن را در دسترس تمام فرزندان فرآیند فعلی قرار میدهد.
نحوهٔ استفاده
# روش اول: تعریف و سپس export MY_VAR="hello" export MY_VAR # روش دوم: تعریف و export یکجا export MY_VAR="hello"
کاربردهای رایج export
-
اضافه کردن مسیر به
PATH:export PATH="/opt/myapp/bin:$PATH"
-
تنظیم متغیرهای پیکربندی برای برنامهها:
export JAVA_HOME="/usr/lib/jvm/java-11-openjdk" export EDITOR="vim"
-
استفاده در اسکریپتها برای ارسال داده به فرمانهای دیگر:
export DB_PASSWORD="secret123" ./my_database_script.sh # این اسکریپت به DB_PASSWORD دسترسی دارد
ماندگاری متغیرهای محیطی
-
متغیرهای محیطی که در ترمینال تنظیم میشوند، فقط تا زمان بستهشدن آن ترمینال معتبرند.
-
برای ماندگاری دائمی، آنها را به فایلهای پیکربندی شل اضافه کنید:
-
برای یک کاربر:
~/.bashrcیا~/.profile -
برای همهٔ کاربران:
/etc/environmentیا/etc/profile
-
رشتهها (Strings)
در Bash، رشتهها دنبالهای از کاراکترها هستند که میتوانند با نقلقولهای تکی (')، نقلقولهای دوتایی (") یا بدون نقلقول نوشته شوند. هرکدام رفتار متفاوتی در برخورد با متغیرها و کاراکترهای خاص دارند.
انواع نقلقولها
| نوع نقلقول | تفسیر متغیرها | تفسیر کاراکترهای خاص (\n, \t, ...) | مثال |
|---|---|---|---|
| بدون نقلقول | بله (با $) | خیر | echo hello $name |
نقلقول دوتایی (") | بله (با $) | بله (با \) | echo "hello $name" |
نقلقول تکی (') | خیر (همهچیز بهصورت متن) | خیر | echo 'hello $name' |
مثالهای عملی
name="Ali" echo "سلام $name" # خروجی: سلام Ali echo 'سلام $name' # خروجی: سلام $name echo سلام $name # خروجی: سلام Ali # استفاده از کاراکترهای خاص echo "خط اول\nخط دوم" # خروجی: خط اول\nخط دوم (چون \n بدون -e تفسیر نمیشود) echo -e "خط اول\nخط دوم" # خروجی در دو خط
عملیات روی رشتهها
۱. طول رشته
برای محاسبهٔ طول یک رشته، از # استفاده کنید:
text="Hello World" echo ${#text} # خروجی: 11
۲. استخراج زیررشته (Substring)
با استفاده از ${string:offset:length} میتوانید بخشی از رشته را استخراج کنید:
text="Hello World" echo ${text:0:5} # خروجی: Hello echo ${text:6} # خروجی: World (از ایندکس ۶ تا انتها)
نکته: ایندکسها در Bash از صفر (0) شروع میشوند.
۳. جایگزینی متن
برای جایگزینی اولین مورد از یک الگو:
text="Hello World World" echo ${text/World/Universe} # خروجی: Hello Universe World
برای جایگزینی همهٔ موارد:
echo ${text//World/Universe} # خروجی: Hello Universe Universe
برای حذف پیشوند یا پسوند (در مسیرها بسیار کاربرد دارد):
path="/home/user/file.txt" echo ${path#/home/} # حذف پیشوند: user/file.txt echo ${path%.txt} # حذف پسوند: /home/user/file
اعداد (Numbers)
در Bash، اعداد بهطور پیشفرض بهعنوان رشته ذخیره میشوند. برای انجام محاسبات ریاضی، باید از دستورات و ساختارهای خاص استفاده کنید.
محاسبات حسابی با (( ))
خوشنویسیترین و سریعترین روش برای محاسبات، استفاده از داخل پرانتز دوتایی (( )) است:
a=10 b=20 # جمع sum=$((a + b)) echo $sum # خروجی: 30 # تفریق، ضرب، تقسیم diff=$((b - a)) mul=$((a * b)) div=$((b / a)) # خروجی: 2 (تقسیم صحیح) mod=$((b % a)) # باقیمانده: 0 # افزایش و کاهش ((a++)) # a میشود 11 ((b--)) # b میشود 19 ((a += 5)) # a میشود 16
محاسبات با expr
دستور قدیمی expr نیز برای محاسبات استفاده میشد، اما امروزه کمتر توصیه میشود:
result=$(expr 10 + 20) echo $result # خروجی: 30
نکته: در
exprباید بین عملوندها و عملگرها فاصله بگذارید.
مقایسهٔ اعداد
برای مقایسهٔ اعداد در شرطها، از عملگرهای زیر استفاده میشود:
a=10 b=20 if [ $a -lt $b ]; then echo "a کوچکتر است" fi # عملگرهای مقایسهای: -eq (مساوی), -ne (نامساوی), -lt (کوچکتر), -le (کوچکتر مساوی), -gt (بزرگتر), -ge (بزرگتر مساوی)
محاسبات با اعداد اعشاری
Bash بهطور پیشفرض از اعداد اعشاری (float) پشتیبانی نمیکند. برای این کار باید از ابزارهایی مانند bc یا awk استفاده کنید:
echo "scale=2; 10/3" | bc # خروجی: 3.33
آرایههای ایندکسی (Indexed Arrays)
آرایهها در Bash، مجموعهای از مقادیر هستند که با یک ایندکس عددی (از صفر شروع میشود) قابل دسترسیاند.
تعریف و مقداردهی
# روش اول: تعریف با پرانتز fruits=("سیب" "موز" "پرتقال") # روش دوم: اختصاص به ایندکسهای خاص colors[0]="قرمز" colors[1]="آبی" colors[2]="سبز"
دسترسی به عناصر
echo ${fruits[0]} # خروجی: سیب echo ${fruits[2]} # خروجی: پرتقال
مشاهدهٔ همهٔ عناصر
echo ${fruits[@]} # خروجی: سیب موز پرتقال echo ${fruits[*]} # خروجی مشابه اما با رفتار متفاوت در نقلقولها
طول آرایه
echo ${#fruits[@]} # خروجی: 3
افزودن عنصر به آرایه
fruits+=("انگور") echo ${fruits[@]} # خروجی: سیب موز پرتقال انگور
حلقه روی آرایه
for fruit in "${fruits[@]}"; do echo "میوه: $fruit" done
نکته: استفاده از
"${array[@]}"با نقلقول دوتایی، از شکستن عناصر دارای فاصله جلوگیری میکند.
آرایههای انجمنی (Associative Arrays)
آرایههای انجمنی در Bash 4 به بالا معرفی شدند و به جای ایندکس عددی، از کلیدهای رشتهای استفاده میکنند. این آرایهها مانند دیکشنری (Dictionary) یا هشمپ (Hashmap) در زبانهای دیگر عمل میکنند.
تعریف و مقداردهی
برای استفاده از آرایههای انجمنی، ابتدا باید آن را با دستور declare -A معرفی کنید:
declare -A user # روش اول user[name]="Ali" user[age]=30 user[city]="Tehran" # روش دوم: تعریف یکجا با پرانتز declare -A product=(["id"]=101 ["name"]="Laptop" ["price"]=1200)
دسترسی به عناصر
echo ${user[name]} # خروجی: Ali echo ${product[price]} # خروجی: 1200
مشاهدهٔ همهٔ کلیدها یا مقادیر
echo ${!user[@]} # خروجی: name age city (کلیدها) echo ${user[@]} # خروجی: Ali 30 Tehran (مقادیر)
حلقه روی آرایهٔ انجمنی
for key in "${!user[@]}"; do echo "$key: ${user[$key]}" done
خروجی نمونه:
name: Ali age: 30 city: Tehran
نکته: ترتیب کلیدها در خروجی تضمینشده نیست.
جمعبندی و بهترین روشها
| نوع داده | نحوهٔ تعریف | نحوهٔ دسترسی | کاربرد |
|---|---|---|---|
| متغیر ساده | name="value" | $name | ذخیرهٔ یک مقدار |
| متغیر محیطی | export name="value" | $name | انتقال مقدار به زیر-فرآیندها |
| رشته | text="Hello" | ${#text} | متن، مسیرها، پیامها |
| عدد | num=10 | $((num + 5)) | محاسبات ریاضی |
| آرایه ایندکسی | arr=("a" "b") | ${arr[0]} | لیستهای مرتب |
| آرایه انجمنی | declare -A map; map[key]="value" | ${map[key]} | دادههای کلید-مقدار |
نکات طلایی
-
همیشه متغیرها را در نقلقول دوتایی قرار دهید، مگر اینکه بخواهید عملیات word splitting انجام شود:
name="Ali Reza" echo $name # خروجی: Ali Reza (با یک فاصله) echo "$name" # خروجی: Ali Reza
-
برای اعداد، از
(( ))استفاده کنید که سریعتر و خواناتر ازexprاست. -
آرایههای انجمنی را حتماً قبل از استفاده با
declare -Aمعرفی کنید. -
متغیرهای محیطی را با حروف بزرگ نامگذاری کنید (رسم رایج) تا از متغیرهای محلی متمایز شوند.
-
برای نمایش محتوای پیچیدهٔ آرایهها، از
declare -pاستفاده کنید که ساختار دقیق آنها را نشان میدهد:declare -p fruits
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: منبع مستندات