198 γραμμές
18 KiB
Markdown
198 γραμμές
18 KiB
Markdown
|
+++
|
|||
|
title = 'Απλός χειρισμός Bash'
|
|||
|
date = '2000-09-01T00:00:00Z'
|
|||
|
description = ''
|
|||
|
author = 'Μιχάλης Καμπριάνης(mailto:kabrianis@hellug.gr)'
|
|||
|
issue = ['Magaz 29']
|
|||
|
issue_weight = 5
|
|||
|
+++
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
*Το standard shell του Linux είναι το bash, γι αυτό, ας μάθουμε μερικά πράγματα για αυτό.*
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
Το Bash είναι ένα shell που χρησιμοποιείται ως standard στο Linux και υπάρχει διαθέσιμο και σαν πηγαίος κώδικας για να προστεθεί σε οποιoδήποτε Unix θέλετε.
|
|||
|
Είναι ένα POSIX-compliant shell και βασικά πρόκειται για μια μετεξέλιξη του shell (sh) συνδυάζοντας τα καλύτερα στοιχεία των C-shell (csh) και Korn-shel (ksh).\
|
|||
|
Το bash υποστηρίζει command-line editing, substitution, filename completion, προχωρημένες δυνατότητες scripting κλπ. Το bash υποστηρίζει βέβαια και
|
|||
|
wildcharacters ή χαρακτήρες-μπαλαντέρ (? για αντικατάσταση ενός χαρακτήρα και \* για αντικατάσταση απεριόριστων χαρακτήρων, `[ ]`
|
|||
|
για καθορισμό εύρους τιμών κλπ. Σε κάθε περίπτωση, αυτό το κείμενο δεν μπορεί παρά να κάνει μία απλή εισαγωγή, και για περισσότερες πληροφορίες που θα οδηγούσαν
|
|||
|
στην πλήρη εκμετάλλευση των δυνατοτήτων του bash, ο αναγνώστης πρέπει να διαβάσει το manual του bash (man bash).
|
|||
|
|
|||
|
**1. Μεταβλητές**
|
|||
|
----------------------------------------
|
|||
|
|
|||
|
**2. Ανακατεύθυνση**
|
|||
|
-------------------------------------------
|
|||
|
|
|||
|
**3. Έξοδος λογικής έκφρασης: test**
|
|||
|
-----------------------------------------------------------
|
|||
|
|
|||
|
**4. Έλεγχοι ροής**
|
|||
|
------------------------------------------
|
|||
|
|
|||
|
**5. Επαναληπτικοί βρόγχοι**
|
|||
|
---------------------------------------------------
|
|||
|
|
|||
|
|
|||
|
### [1. Μεταβλητές]{#s1}
|
|||
|
|
|||
|
Οι μεταβλητές (βασικό στοιχείο σε κάθε πρόγραμμα) στο bash δεν είναι προκαθορισμένου τύπου, μπορεί δηλαδή η ίδια μεταβλητή να έχει αριθμητική τιμή, ή τιμή
|
|||
|
κειμένου (string) κλπ χωρίς να το προδηλώσουμε πουθενά (αν και για το bash όλες οι μεταβλητές είναι strings, με την χρήση της eval μπορούμε να κάνουμε και
|
|||
|
αριθμητικές πράξεις αν τα strings αποτελούνται μόνο από αριθμούς). Οι μεταβλητές ορίζονται με απλή τοποθέτηση (assignment, π.χ. var=1) και προσπελαύνονται
|
|||
|
βάζοντας μπροστά από το όνομά τους το σύμβολο \$. Αν η τιμή μίας μεταβλητής εσωκλείεται σε διπλά εισαγωγικά \"\", τότε το bash αγνοεί οποιαδήποτε κενά
|
|||
|
βρίσκονται εκεί. Αν δεν τα αγνοούσε, η τιμή της μεταβλητής θα ήταν οτιδήποτε υπάρχει μέχρι το πρώτο κενό. Ότι ήταν μετά το κενό θα θεωρούνταν ως τιμή της
|
|||
|
δεύτερης μεταβλητής, κάτι το οποίο έχει ιδιαίτερο νόημα για παραμέτρους που δίνονται από την γραμμή εντολών κατά την κλήση του προγράμματος. Αν εσωκλείεται σε
|
|||
|
ανάποδα μονά εισαγωγικά \`, τότε εννοείται ότι πρόκειται περί εντολής, η οποία θα εκτελεστεί και το αποτέλεσμα της εντολής θα αποτελεί την τιμή της μεταβλητής.
|
|||
|
|
|||
|
Το bash χρησιμοποιεί κάποιες προκαθορισμένες μεταβλητές για τα διάφορα \"προγραμματάκια\" που μπορούμε να φτιάξουμε. Αυτές είναι οι:
|
|||
|
|
|||
|
- \$\# Ο αριθμός των παραμέτρων που δώσαμε στην γραμμή εντολών.
|
|||
|
- \$0 Η πρώτη λέξη της κληθείσας εντολής (πρακτικά δηλαδή το όνομα του προγράμματος).
|
|||
|
- \$1 - \$N Οι παράμετροι που δώσαμε στην γραμμή εντολών (όπου \$1 η πρώτη παράμετρος, και N ίσο με το \$\#).
|
|||
|
- \$@ Φυλάσσει το σύνολο των παραμέτρων της γραμμής εντολών (δηλαδή από \$1 μέχρι \$N όπως ακριβώς τις γράψαμε.) σε μορφή πίνακα (array).
|
|||
|
- \$\* Φυλάσσει το σύνολο των παραμέτρων της γραμμής εντολών (δηλαδή από \$1 μέχρι \$N όπως ακριβώς τις γράψαμε) σε μία μεταβλητή (μία και μόνη, τύπου
|
|||
|
string).
|
|||
|
- \$? Σε αυτή τη μεταβλητή φυλάσσεται το αποτέλεσμα εξόδου της προηγούμενης εντολής.
|
|||
|
|
|||
|
|
|||
|
### [2. Ανακατεύθυνση]{#s2}
|
|||
|
|
|||
|
Το bash υποστηρίζει όπως θα ήταν ίσως αναμενόμενο, ανακατεύθυνση των τριών βασικών file descriptors, δηλαδή των standard input, standard output και standard
|
|||
|
error (αντίστοιχα 0, 1 και 2). Η ανακατεύθυνση της εισόδου γίνεται με το σύμβολο \<, και η ανακατεύθυνση εξόδου (και εξόδου λάθους) με το σύμβολο \> γράφοντας
|
|||
|
και τον αριθμό του file descriptor. Δηλαδή η έκφραση command 1\> output θα ανακατευθύνει την κανονική έξοδο στο αρχείο output (και είναι ισοδύναμη με την
|
|||
|
command \> output) ενώ η έκφραση command 2\> error θα ανακατευθύνει την έξοδο λάθους στο αρχείο error. Για να ανακατευθύνουμε και την κανονική έξοδο, αλλά και
|
|||
|
την έξοδο λάθους σε ένα αρχείο, μπορούμε να χρησιμοποιήσουμε οποιαδήποτε από τις ακόλουθες εκφράσεις:
|
|||
|
`command &> out, command >& out, command 2>&1 out`
|
|||
|
|
|||
|
Τέλος, το bash υποστηρίζει και piping, να ανακατευθύνει δηλαδή την έξοδο μίας εντολής, στην είσοδο μίας άλλης εντολής, με το σύμβολο \|.
|
|||
|
|
|||
|
|
|||
|
### [3. Έξοδος λογικής έκφρασης: test]{#s3}
|
|||
|
|
|||
|
Όποτε θέλουμε να ελέγξουμε το αποτέλεσμα μίας λογικής ή αριθμητικής έκφρασης χρησιμοποιούμε τη συνάρτηση test. Η συνάρτηση test επιστρέφει τιμή \"αληθής\" ή
|
|||
|
\"ψευδής\" ανάλογα με το αληθές ή ψευδές της λογικής (ή και αριθμητικής) έκφρασης που ελέγχεται. H συνάρτηση test μπορεί να γραφεί και ώς `[ έλεγχος ]` . Η
|
|||
|
έκφραση μπορεί να έχει ένα μόνο στοιχείο και έναν τελεστή (ο οποίος έτσι ονομάζεται unary operator) ή μπορεί να έχει δύο στοιχεία και έναν τελεστή ο οποίος
|
|||
|
ονομάζεται binary operator. Πιο πολλές πληροφορίες από το manual page της συνάρτησης test το οποίο μπορείτε να δείτε γράφοντας man test
|
|||
|
|
|||
|
Οι πιο συνηθισμένοι τελεστές:
|
|||
|
|
|||
|
- `test [ 1 -eq 2 ]`\
|
|||
|
Η ανωτέρω έκφραση είναι ψευδής γιατί ο (αριθμητικός) τελεστής -eq σημαίνει ισότητα (equal). Άλλοι αριθμητικοί τελεστές είναι οι:
|
|||
|
1. -gt ο αριθμός αριστερά είναι μεγαλύτερος από τον αριθμό δεξιά (greater than).
|
|||
|
2. -lt ο αριθμός δεξιά είναι μικρότερος από τον αριθμό αριστερά (less than).
|
|||
|
3. -ne οι δύο αριθμοί δεν είναι ίσοι (not equal).
|
|||
|
4. -ge ο αριθμός αριστερά είναι μεγαλύτερος ή ίσος από τον αριθμό δεξιά (greater or equal).
|
|||
|
5. -le ο αριθμός αριστερά είναι μικρότερος ή ίσος από τον αριθμό δεξιά (less or equal).
|
|||
|
- `test [ like = likme ]`\
|
|||
|
Η ανωτέρω έκφραση είναι ψευδής γιατί ο (λογικός) τελεστής = σημαίνει ότι τα δύο strings που συγκρίνουμε είναι ίσα (ίδια). Άλλοι λογικοί τελεστές σχετικοί με
|
|||
|
strings είναι οι:
|
|||
|
1. != ο οποίος προφανώς επιστρέφει \"αληθές\" όταν τα δύο strings που συγκρίνουμε είναι ανόμοια.
|
|||
|
2. -z ο οποίος είναι unary operator (συντάσσεται δηλαδή ως εξής: `test [ -z string ]`) επιστρέφει \"αληθές\" αν το μήκος του string είναι μηδενικό.
|
|||
|
3. -n που είναι και αυτός unary operator (συντάσσεται δηλαδή ως εξής: `test [ -n string ]`) επιστρέφει \"αληθές\" αν το μήκος του string δεν είναι
|
|||
|
μηδενικό.
|
|||
|
- `test [ -e filename ]`\
|
|||
|
Η ανωτέρω έκφραση βγαίνει αληθής όταν το αρχείο με όνομα filename υπάρχει. Άλλοι τελεστές ελέγχου της κατάστασης ενός αρχείου είναι οι εξής (όλοι όσοι
|
|||
|
αναφέρονται εδώ είναι unary operators):
|
|||
|
1. -b αν το αρχείο υπάρχει και είναι block device
|
|||
|
2. -c αν το αρχείο υπάρχει και είναι character device
|
|||
|
3. -d αν το αρχείο υπάρχει και είναι directory
|
|||
|
4. -f αν το αρχείο υπάρχει και είναι κανονικό αρχείο
|
|||
|
5. -r αν το αρχείο υπάρχει και μπορεί να διαβαστεί
|
|||
|
6. -s αν το αρχείο υπάρχει και το μέγεθος του δεν είναι μηδέν
|
|||
|
7. -w αν το αρχείο υπάρχει και μπορεί να γραφτεί
|
|||
|
8. -x αν το αρχείο υπάρχει και μπορεί να εκτελεστεί
|
|||
|
|
|||
|
|
|||
|
### [4. Έλεγχοι ροής]{#s4}
|
|||
|
|
|||
|
- if - then - else
|
|||
|
|
|||
|
Ένας τρόπος και ο πιο συνηθισμένος ελέγχου ροής ενός προγράμματος είναι ο έλεγχος if-then-else όπου ελέγχουμε το αποτέλεσμα μίας λογικής έκφρασης και
|
|||
|
ανάλογα με αυτό το αποτέλεσμα καθορίζουμε τι θα κάνει το πρόγραμμα. Προφανώς ο έλεγχος χρησιμοποιεί το αποτέλεσμα της συνάρτησης test για να καθορίσει την
|
|||
|
ροή. Για παράδειγμα
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
if [ $i -eq 3 ]; then
|
|||
|
echo 'Number is 3';
|
|||
|
elif [ $i -eq 2 ]; then
|
|||
|
echo 'Number is 2';
|
|||
|
else echo 'Number is neither 3 nor 2';
|
|||
|
fi
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
όπου είναι προφανές ότι κάπου στο πρόγραμμά μας έχουμε δώσει τιμή στην παράμετρο \$i. Μπορούμε να έχουμε όσα elif θέλουμε, αρκεί στο τέλος να υπάρχει και
|
|||
|
ένα else. Αν δεν υπάρχει κανέναν elif δεν είναι υποχρεωτικό και το else, είναι όμως σε κάθε περίπτωση υποχρεωτικό το fi.
|
|||
|
|
|||
|
- select
|
|||
|
|
|||
|
Η συνάρτηση select δουλεύει (και συντάσσεται) όπως η if αλλά δίνει τη δυνατότητα να δημιουργήσουμε menu. Για παράδειγμα
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
select i in a.txt b.txt c.txt; do
|
|||
|
cat $i;
|
|||
|
done
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
Το ανωτέρω παράδειγμα παρουσιάζει στον χρήστη ένα menu με τρεις επιλογές και ανάλογα με την επιλογή του χρήστη, του εμφανίζει το αντίστοιχο αρχείο στην
|
|||
|
οθόνη.
|
|||
|
|
|||
|
- case
|
|||
|
|
|||
|
Η συνάρτηση case τέλος, προσομοιάζει στην αντίστοιχη συνάρτηση της C και σαν σύνταξη, αλλά και σαν αποτέλεσμα, και συγκεκριμένα εκτελεί προκαθορισμένες
|
|||
|
εντολές για προκαθορισμένες τιμές μίας μεταβλητής, έχοντας ταυτόχρονα και μία γενική περίπτωση που δεν εμπίπτει στις υπόλοιπες. Για παράδειγμα
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
case $i in
|
|||
|
1 | 3 | 5 | 7 | 9) echo -n "Odd one-digit number";;
|
|||
|
0 | 2 | 4 | 6 | 8) echo -n "Even one-digit number";;
|
|||
|
*) echo -n "It definitely is not a one-digit nummber";;
|
|||
|
esac
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
Το ανωτέρω παράδειγμα ελέχει την μεταβλητή \$i που υποτίθεται ότι κάπου πιο πριν την έχουμε δώσει, και μας απαντάει αν είναι μονός ή ζυγός μονοψήφιος
|
|||
|
αριθμός, ή όχι.
|
|||
|
|
|||
|
|
|||
|
### [5. Επαναληπτικοί βρόγχοι]{#s5}
|
|||
|
|
|||
|
- for - do
|
|||
|
|
|||
|
Ο βρόγχος for - do είναι ο πιο συνηθισμένος σε όλες τις γλώσσες προγραμματισμού. Η χρήση του είναι απλούστατη ειδικά στο bash όπου \\textbf{δεν μπορούμε να
|
|||
|
ορίσουμε πεδίο τιμών, αντ\' αυτού είμαστε υποχρεωμένοι να ορίζουμε τις τιμές μία μία, ακόμα και αν αυτές είναι κατά κάποια έννοια συνεχόμενες. Ένα
|
|||
|
παράδειγμα είναι το απλούστατο:
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
for i in 1 3 5 ; do
|
|||
|
echo $i;
|
|||
|
done
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
Το πεδίο τιμών της μεταβλητής \$i δεν αποτελείται υποχρεωτικά από αριθμούς αλλά μπορεί να είναι και λέξεις ή γράμματα, ή ακόμα και wildcharacters (\* και ?)
|
|||
|
κάνοντας έτσι αυτό τον βρόγχο ένα πανίσχυρο εργαλείο.
|
|||
|
|
|||
|
- while - do Η συνάρτηση while εκτελεί κάποιες εντολές όσο μία λογική έκφραση είναι αληθής. Το κλασικότερο παράδειγμα είναι η δημιουργία ενός επαναληπτικού
|
|||
|
βρόγχου, ως εξής:
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
while [ $i -lt 10 ]; do
|
|||
|
read i;
|
|||
|
echo $i;
|
|||
|
done
|
|||
|
|
|||
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|||
|
|
|||
|
Προφανώς το παράδειγμα αυτό θα μας εμφανίζει συνέχεια ότι του γράφουμε μέχρι να δώσουμε ένα αριθμό μεγαλύτερο (ή ίσο) του 10. Προσοχή χρειάζεται εδώ, γιατί
|
|||
|
στο πρόγραμμά μας η μεταβλητή \$i πρέπει να έχει τιμή πριν κληθεί η while.
|
|||
|
|