تستطيع Bash إجراء الحساب، لكن بالأعداد الصحيحة فقط. وإذا احتجت إلى إجراء حسابات بالفاصلة العائمة، فستحتاج إلى الاستعانة ببرنامج خارجي (مثل awk أو bc).
العوامل الحسابية مدرجة (بترتيب الأسبقية) في الدليل: حساب الصدفة.
بالإضافة إلى ذلك، لا تُجري Bash الحساب إلا في مواضع معينة (تُعرف بسياقات الحساب).
يشبه توسيع الحساب استبدال الأوامر، لكنه يستخدم الأقواس الهلالية المزدوجة.
$(( expression ))
يتوسّع هذا التركيب إلى نتيجة تقييم التعبير. ويُستخدم عادةً لتخزين النتيجة في متغير:
x=$(( 3 + 4 ))
مقدار المسافات البيضاء داخل الأقواس متروك لك. إنها مسألة أسلوب ووضوح.
x=$(( 3 + 4 ))
y=$((5+6))
يحب كاتبك الودود إضافة مسافات ليكون تعبير الحساب أكثر وضوحًا داخل الأقواس.
يُنفَّذ الشرط الحسابي داخل الأقواس الهلالية المزدوجة بدون علامة $ في البداية:
(( expression ))
هذا لا يتوسّع إلى النتيجة. لكنه يُنتج حالة خروج.
داخل (( تستخدم Bash المنطق نفسه للصحيح والخطأ كما في لغة C: الصفر خطأ، وما لا يساوي صفرًا صحيح.
وهذا عكس الطريقة التي تقيّم بها Bash حالات الخروج!
يُستخدم هذا التركيب عادةً في موضعين:
كجزء الأمر في جملة 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]}"
# ................................^^^^^
لمزيد عن المصفوفات، اقرأ مستند مفهوم المصفوفات.
جزءا الإزاحة والطول في توسيع ${var:offset:length}.
(( 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 ))