Bash अंकगणित कर सकता है, लेकिन सिर्फ पूर्णांकों के साथ। अगर आपको दशमलव संख्याओं का गणित करना है, तो आपको किसी बाहरी प्रोग्राम को कॉल करना पड़ेगा (जैसे awk या bc)।
अंकगणित के ऑपरेटर मैनुअल में (प्राथमिकता के क्रम में) दिए गए हैं: Shell Arithmetic।
इसके अलावा, Bash अंकगणित सिर्फ कुछ खास जगहों पर ही करता है (जिन्हें अंकगणित के "कॉन्टेक्स्ट" कहते हैं)।
अंकगणितीय एक्सपैंशन कमांड सबस्टिट्यूशन जैसा दिखता है, बस इसमें दोहरे ब्रैकेट होते हैं।
$(( expression ))
यह सिंटैक्स एक्सप्रेशन को हल करने के परिणाम में एक्सपैंड हो जाता है। आमतौर पर इसे किसी वेरिएबल में परिणाम सहेजने के लिए इस्तेमाल किया जाता है:
x=$(( 3 + 4 ))
ब्रैकेट के अंदर कितने स्पेस डालने हैं, यह आप पर निर्भर है। यह स्टाइल और पठनीयता की बात है।
x=$(( 3 + 4 ))
y=$((5+6))
आपका मित्रवत लेखक स्पेस जोड़ना पसंद करता है, ताकि ब्रैकेट के अंदर अंकगणितीय एक्सप्रेशन ज़्यादा साफ नज़र आए।
अंकगणितीय कंडीशनल दोहरे ब्रैकेट के अंदर किया जाता है, बिना शुरू के $ के:
(( expression ))
यह परिणाम के रूप में एक्सपैंड नहीं होता। लेकिन यह एक एग्ज़िट स्टेटस बनाता है।
(( के अंदर Bash सही/गलत का वही मतलब लेता है जो C भाषा लेती है: शून्य गलत है, गैर-शून्य सही।
Bash एग्ज़िट स्टेटस को जिस तरह देखता है, यह उससे बिल्कुल उल्टा है!
यह सिंटैक्स आमतौर पर दो जगहों पर इस्तेमाल होता है:
किसी if स्टेटमेंट या while लूप के COMMAND वाले हिस्से के रूप में।
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"
++ ऑपरेटर पर विस्तृत चर्चा के लिए Postincrement vs Preincrement पर यह लेख देखिए।
कुछ और जगहें भी हैं जो अंकगणितीय कॉन्टेक्स्ट हैं:
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 ))