Το Bash μπορεί να κάνει αριθμητική, αλλά μόνο με ακέραιους αριθμούς. Αν χρειάζεται να κάνεις μαθηματικά με κινητή υποδιαστολή, θα πρέπει να καλέσεις κάποιο εξωτερικό πρόγραμμα (όπως το awk ή το bc).
Οι αριθμητικοί τελεστές παρατίθενται (κατά σειρά προτεραιότητας) στο εγχειρίδιο: Shell Arithmetic.
Επιπλέον, το 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"
Για μια πιο εκτενή συζήτηση σχετικά με τον τελεστή ++, δες αυτό το άρθρο για το 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 ))