Bash میتواند محاسبات انجام دهد، اما فقط با اعداد صحیح.
اگر لازم است محاسبات اعشاری انجام دهید، باید به سراغ یک برنامهی بیرونی بروید (مثل awk یا bc).
عملگرهای محاسباتی به ترتیب تقدم در راهنما فهرست شدهاند: حساب در پوسته.
بهعلاوه، Bash فقط در جاهای مشخصی محاسبات انجام میدهد (که به آنها «زمینههای محاسباتی» میگویند).
بسط محاسباتی شبیه جانشینی دستور است، اما با پرانتزهای دوتایی.
$(( expression ))
این نحوهی نگارش به نتیجهی ارزیابی عبارت بسط مییابد. معمولاً از آن برای ذخیرهی نتیجه در یک متغیر استفاده میشود:
x=$(( 3 + 4 ))
میزان فاصلهی داخل پرانتزها به خودتان بستگی دارد. این موضوع به سلیقه و خوانایی مربوط است.
x=$(( 3 + 4 ))
y=$((5+6))
نویسندهی مهربان شما دوست دارد فاصله اضافه کند تا عبارت محاسباتی داخل پرانتزها بهتر دیده شود.
شرط محاسباتی داخل پرانتزهای دوتایی و بدون $ ابتدایی اجرا میشود:
(( expression ))
این شکل به نتیجه بسط نمییابد. اما یک «وضعیت خروج» تولید میکند.
داخل ((، Bash همان برداشت «درست»/«غلط» زبان C را به کار میبرد: صفر «غلط» است و غیرصفر «درست».
این دقیقاً برعکس روشی است که Bash وضعیتهای خروج را با آن ارزیابی میکند!
معمولاً از این نحوهی نگارش در دو جا استفاده میشود:
بهعنوان بخش COMMAND یک دستور if یا یک حلقهی while.
if (( x == y - 1 )); then ...
while (( y > 0 )); do ...
بهعنوان یک دستور مستقل برای تغییر مقدار یک متغیر.
(( x = x + 1 ))
echo "new value for x is $x"
در استفاده از محاسبات به این شکل همراه با set -e احتیاط کنید.
اگر نتیجهی عبارت صفر شود، وضعیت خروج غیرصفر میشود و Bash خاتمه مییابد.
x=0
(( x++ ))
echo "you will see this"
set -e
x=0
(( x++ ))
echo "shell exits on the previous line; you won't see this"
برای بحث مفصلتر دربارهی عملگر ++، این مقاله را ببینید: پسافزایش در برابر پیشافزایش
چند جای دیگر هم وجود دارد که زمینهی محاسباتی دارند:
for (( i = 0; i < 10; i++ )); do
echo "$i"
done
بخش ایندکس یک آرایهی دارای ایندکس عددی.
echo "The next element is ${array[x + 1]}"
# ................................^^^^^
برای اطلاعات بیشتر دربارهی آرایه، صفحهی مفهوم آرایه را بخوانید.
بخشهای offset و length از بسط ${var:offset:length}.
دستور توکار let.
(( expression )) به let "expresson" ترجیح داده میشود.
برخلاف ساختار شرط محاسباتی، عبارت let در معرض بسط نام فایل و شکستن واژه قرار میگیرد و به نقلقول نیاز دارد.تخصیص متغیر، زمانی که متغیر «ویژگی عدد صحیح» داشته باشد.
# variable x does not have the integer attribute
x="3 + 4"
declare -p x # => declare -- x="3 + 4"
# variable y has the integer attribute
declare -i y
y="4 + 5"
declare -p y # => declare -i y="9"
به عقیدهی نویسنده، declare -i کاربرد محدودی دارد.
مزیت اصلی آن این است که اجازه میدهد محاسبات را «خام» انجام دهید (بدون نگارش عبارت محاسباتی).
این میتواند برای خوانندگان کد شما گیجکننده باشد، چون عبارتهای محاسباتی در جاهای غیرمنتظره ارزیابی میشوند.
اینجا یکی از جنبههای زمینههای محاسباتی را میبینید که خوانایی را بهبود میدهد.
height=10
width=20
area=$(( height * width ))
آیا متوجه شدید که علامتهای دلار $ از متغیرهای داخل عبارت محاسباتی حذف شدهاند؟
Bash به شما اجازه میدهد این کار را بکنید.
این کار خواندن عبارتها را بسیار آسانتر میکند.
راهنما میگوید:
درون یک عبارت، متغیرهای پوسته را میتوان با اسم و بدون استفاده از نحوهی نگارش بسط پارامتر ارجاع داد.
حتی برای عناصر آرایه هم کار میکند:
point1=(10 15) # these are (x, y) coordinates
point2=(20 7)
distance_squared=$(( (point1[0] - point2[0])**2 + (point1[1] - point2[1])**2 ))
اما سایر عبارتهای پارامتری باید از نگارش ویژهی خود استفاده کنند. مثلاً دو برابر کردن طول یک رشته:
s="hello world"
len=$(( ${#s} * 2 ))
و پارامترهای موقعیتی هم به همین شکل باید از نگارش ویژهی خود استفاده کنند. اگر دو پارامتر موقعیتی اول نمایندهی عرض و ارتفاع باشند:
area=$(( $1 * $2 ))