المسارات
/
Bash
Bash
/
المنهج
/
العمليات الحسابية
ال

العمليات الحسابية في Bash

{zero: "لا توجد تمارين", one: "1 تمرين", two: "تمرينان", few: "%{count} تمارين", many: "%{count} تمرينًا", other: "%{count} تمرين"}

نبذة عن العمليات الحسابية

تستطيع Bash إجراء الحساب، لكن بالأعداد الصحيحة فقط. وإذا احتجت إلى إجراء حسابات بالفاصلة العائمة، فستحتاج إلى الاستعانة ببرنامج خارجي (مثل awk أو bc).

العوامل الحسابية مدرجة (بترتيب الأسبقية) في الدليل: حساب الصدفة.

بالإضافة إلى ذلك، لا تُجري Bash الحساب إلا في مواضع معينة (تُعرف بسياقات الحساب).

توسيع الحساب

يشبه توسيع الحساب استبدال الأوامر، لكنه يستخدم الأقواس الهلالية المزدوجة.

$(( expression ))

يتوسّع هذا التركيب إلى نتيجة تقييم التعبير. ويُستخدم عادةً لتخزين النتيجة في متغير:

x=$(( 3 + 4 ))
Note

مقدار المسافات البيضاء داخل الأقواس متروك لك. إنها مسألة أسلوب ووضوح.

x=$(( 3 + 4 ))
y=$((5+6))

يحب كاتبك الودود إضافة مسافات ليكون تعبير الحساب أكثر وضوحًا داخل الأقواس.

الشرط الحسابي

يُنفَّذ الشرط الحسابي داخل الأقواس الهلالية المزدوجة بدون علامة $ في البداية:

(( expression ))

هذا لا يتوسّع إلى النتيجة. لكنه يُنتج حالة خروج.

  • تكون حالة الخروج 0 (نجاح) إذا كانت نتيجة التعبير لا تساوي صفرًا.
  • وتكون حالة الخروج 1 (فشل) إذا كانت نتيجة التعبير تساوي صفرًا.
Note

داخل (( تستخدم Bash المنطق نفسه للصحيح والخطأ كما في لغة C: الصفر خطأ، وما لا يساوي صفرًا صحيح. وهذا عكس الطريقة التي تقيّم بها Bash حالات الخروج!

يُستخدم هذا التركيب عادةً في موضعين:

  1. كجزء الأمر في جملة if أو حلقة while.

    if (( x == y - 1 )); then ...
    while (( y > 0 )); do ...
    
  2. كأمر مستقل لتعديل قيمة متغير.

    (( x = x + 1 ))
    echo "new value for x is $x"
    
    Caution

    كن حذرًا عند استخدام الحساب بهذه الطريقة مع 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 الحسابية.

    for (( i = 0; i < 10; i++ )); do
        echo "$i"
    done
    
  • جزء الفهرس في مصفوفة ذات فهرسة عددية.

    echo "The next element is ${array[x + 1]}"
    # ................................^^^^^
    

    لمزيد عن المصفوفات، اقرأ مستند مفهوم المصفوفات.

  • جزءا الإزاحة والطول في توسيع ${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"
    
    Note

    يرى الكاتب أن استخدام 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 ))
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة