Οδηγός Bash για αρχαρίους

Machtelt Garrels

Xalasys.com


<tille wants no spam _at_ xalasys dot com>

Έκδοση 1.8  Ενημέρωση 20060315 

Πρώτη έκδοση Ελληνικής μετάφρασης Φεβρουάριος 2008


Περιεχόμενα

Εισαγωγή

1. Γιατί αυτός ο οδηγός;

2. Ποιός πρέπει να διαβάσει αυτό το βιβλίο;

3. Νέες εκδόσεις, μεταφράσεις και διαθεσιμότητα

4. Ιστορικό αναθεωρήσεων

5. Συνεισφορές

6. Ανάδραση

7. Πληροφορίες Copyright

8. Τι χρειάζεστε;

9. Συμβάσεις του κειμένου

10. Οργάνωση του κειμένου

1. Bash και σενάρια Bash

1.1. Κοινά προγράμματα φλοιού

1.2. Πλεονεκτήματα του Bash (Bourne Again SHell)

1.3. Eκτέλεση εντολών

1.4. Δομικά μέρη

1.5. Ανάπτυξη καλών σεναρίων

1.6. Περίληψη

1.7. Ασκήσεις

2. Συγγραφή και εκσφαλμάτωση σεναρίων

2.1. Δημιουργία και εκτέλεση ενός σεναρίου

2.2. Τα βασικά των σεναρίων

2.3. Εκσφαλμάτωση σεναρίων Bash

2.4. Περίληψη

2.5. Ασκήσεις

3. Το περιβάλλον Bash

3.1. Αρχεία ρύθμισης φλοιού

3.2. Μεταβλητές

3.3. Χαρακτήρες σε εισαγωγικά

3.4. Επέκταση φλοιού

3.5. Ψευδώνυμα

3.6. Άλλες επιλογές του Bash

3.7. Περίληψη

3.8. Ασκήσεις

4. Κανονικές εκφράσεις

4.1. Κανονικές εκφράσεις

4.2. Παραδείγματα με το grep

4.3. Ταύτιση προτύπων με το Bash

4.4. Περίληψη

4.5. Ασκήσεις

5. Ο συντάκτης ροής GNU sed

5.1. Εισγαωγή

5.2. Διαλογική σύνταξη

5.3. Μη-διαλογική σύνταξη

5.4. Περίληψη

5.5. Ασκήσεις

6. Η γλώσσα προγραμματισμού GNU awk

6.1. Εκκίνηση με την gawk

6.2. Το πρόγραμμα print

6.3. Μεταβλητές gawk

6.4. Περίληψη

6.5. Ασκήσεις

7. Δηλώσεις απόφασης

7.1. Εισαγωγή στο if

7.2. Προχωρημένη χρήση του if

7.3. Δηλώσεις case

7.4. Περίληψη

7.5. Ασκήσεις

8. Συγγραφή διαλογικών σεναρίων

8.1. Εμφάνιση μηνυμάτων χρήστη

8.2. Λήψη εισόδου χρήστη

8.3. Περίληψη

8.4. Ασκήσεις

9. Επαναληπτικές εργασίες

9.1. Ο βρόχος for

9.2. Ο βρόχος while

9.3. Ο βρόχος until

9.4. Ανακατεύθυνση Ε/Ε και βρόχοι

9.5. Break και continue

9.6. Δημιουργία menu με τη select

9.7. Η εντολή shift

9.8. Περίληψη

9.9. Ασκήσεις

10. Περισσότερα για μεταβλητές

10.1. Τύποι μεταβλητών

10.2. Πίνακες μεταβλητών

10.3. Λειτουργίες σε μεταβλητές

10.4. Περίληψη

10.5. Ασκήσεις

11. Συναρτήσεις

11.1. Εισαγωγή

11.2. Παραδείγματα συναρτήσεων σε σενάρια

11.3. Περίληψη

11.4. Ασκήσεις

12. Λήψη σημάτων

12.1. Σήματα

12.2. Παγίδες

12.3. Περίληψη

12.4. Ασκήσεις

A. Χαρακτηριστικά φλοιών

A.1. Κοινά χαρακτηριστικά

A.2. Διαφορετικά χαρακτηριστικά

B. GNU Free Documentation License

B.1. Preamble

B.2. Applicability and definitions

B.3. Verbatim copying

B.4. Copying in quantity

B.5. Modifications

B.6. Combining documents

B.7. Collections of documents

B.8. Aggregation with independent works

B.9. Translation

B.10. Termination

B.11. Future revisions of this license

B.12. How to use this License for your documents

Ευρετήριο

Λίστα πινάκων

1. Τυπογραφικές και χρηστικές συμβάσεις

1-1. Επισκόπηση  προγραμματιστικών όρων

2-1. Επισκόπηση επιλογών εκσφαλμάτωσης

3-1. Δεσμευμένες μεταβλητές φλοιού Bourne

3-2. Δεσμευμένες μεταβλητές φλοιού Bash

3-3. Ειδικές μεταβλητές Bash 

3-4. Αριθμητικοί τελεστές

4-1. Τελεστές κανονικών εκφράσεων

5-1. Εντολές σύνταξης sed

5-2. Επιλογές sed

6-1. Χαρακτήρες μορφοποίησης gawk

7-1. Βασικές εκφράσεις

7-2. Συνδυασμοί εκφράσεων

8-1. Ακολουθίες διαφυγής της echo

8-2. Επιλογές read 

10-1. Επιλογές declare

12-1. Σήματα ελέγχου στο Bash

12-2. Συνηθισμένα σήματα τερματισμού

A-1. Κοινά χαρακτηριστικά φλοιών

A-2. Διαφορετικά χαρακτηριστικά φλοιών

Λίστα εικόνων

1. Bash Guide for Beginners : εξώφυλλο

2-1. script1.sh

3-1. Διαφορετικές προτροπές για διαφορετικούς χρήστες

6-1. Πεδία στην awk

7-1. Έλεγχος ορισμάτων γραμμής εντολών με if

7-2. Παράδειγμα χρήσης λογικών τελεστών


Εισαγωγή

1. Γιατί αυτός ο οδηγός;

Ο πρωταρχικός λόγος για την συγγραφή αυτού του οδηγού είναι ότι πολλοί αναγνώστες νοιώθουν ότι το υπάρχον HOWTO είναι πολυ σύντομο και ατελές, ενώ ο οδηγός Bash Scripting είναι περισσότερο έργο αναφοράς.  Δεν υπάρχει τίποτε μεταξύ αυτών των δύο άκρων. Επίσης έγραψα αυτό τον οδηγό με τη γενική αρχή ότι δεν υπάρχουν τόσα δωρεάν βασικά μαθήματα διαθέσιμα, όσα θα έπρεπε να υπάρχουν.  

Πρόκειται για ένα πρακτικό οδηγό, ο οποίος, ενώ δεν είναι υπερβολικά σοβαρός, προσπαθεί να δώσει πραγματικά, καθημερινά παραδείγματα αντί για θεωρητικά. Εν μέρει το έγραψα αυτό επειδή δεν ενθουσιάζομαι με υπέρ-απλουστευμένα παραδείγματα γραμμένα από ανθρώπους που ξέρουν για τι πράγμα μιλάνε, δείχνοντας μερικά έξυπνα χαρακτηριστικά του Bash, τα οποία είναι τόσο έξω από το πλαίσιο τους ώστε να μην μπορείς να τα χρησιμοποιήσεις ποτέ σε πραγματικές συνθήκες. Μπορείτε να διαβάσετε τέτοια πράγματα αφού θα τελειώσετε αυτό τον οδηγό, ο οποίος περιέχει ασκήσεις και παραδείγματα, που θα σας βοηθήσουν να επιζήσετε στον πραγματικό κόσμο.

Από την εμπειρία μου ως χρήστης UNIX/Linux, διαχειριστής συστημάτων και εκπαιδευτής, ξέρω οτι πολλοί χρήστες μπορεί να χρησιμοποιούν χρόνια το σύστημά τους χωρίς να έχουν τη παραμικρή kγνώση για αυτοματοποίηση εργασιών. Έτσι συχνά θεωρούν οτι το UNIX δεν είναι φιλικό, ή ακόμη χειρότερα, οτι είναι αργό και ξεπερασμένο. Αυτό είναι ένα άλλο πρόβλημα που μπορείνα διορθωθεί με αυτό τον οδηγό.


2. Ποιός πρέπει να διαβάσει αυτό τον οδηγό;

Καθένας που δουλεύει σε συστήματα UNIX ή παρόμοια συστήματα και θέλει να κάνει τη ζωή του ευκολότερη, είτε είναι διαχειριστής ή ισχυρός χρήστης, μπορεί να κερδίσει από την ανάγνωση αυτού του εγχειριδιίου. Οι αναγνώστες που ήδη γνωρίζουν τη χρήση της γραμμής εντοών θα μάθουν να διευκολύνουν τις καθημερινές τους εργασίες με τη συγγραφή σεναρίων. Οι διχαχειριστές συστημάτων βασίζονται πολύ στα σενάρια φλοιού για την αυτοματοποίηση συχνά εκτελούμενων εργασιών. Το κείμενο αυτό είναι γεμάτο παραδείγματα που θα σας ενθαρρύνουν να γράψετε τα δικά σας σενάρια και θα σας εμπνεύσει να βελτιώσετε υπάρχοντα σενάρια.

Προαπαιτούμενα (ή μη) για την ανάγνωση: Πρέπει να:

·         Είστε ένας έμπειρος χρήστης UNIX ή Linux, εξοικειωμένος με τις βασικές εντολές και τις σελίδες τεκμηρίωσης

·         Μπορείτε να χρησιμοποιήσετε ένα συντάκτη κειμένου

·         Κατανοείτε τη διαδικασία εκκίνσης και τερματισμού, το init και τα initscripts

·         Μπορείτε να δημιουργείτε χρήστες, ομάδες και να ρυθμίζετε κωδικούς πρόσβασης

·         Γνωρίζετε τα ζητήματα διαχείρισης αδειών πρόσβασης αρχείων

·         Κατανοείτε τις συμβάσεις ονομασίας συσκευών, διαμέρισης, από/προσάρτησης συστημάτων αρχείων

·         Μπορείτε να προσθαφαιρείτε λογισμικό στο σύστημά σας

Σε περίπτωση που δεν γνωρίζετε κάποιο από τα παραπάνω θέματα δείτε την Εισαγωγή στο Linux (ή το τοπικό TLDP mirror). Πρόσθετες πληροφορίες μπορούν να βρεθούν στη τεκμηρίωση του συστήματος (σελίδες man και info), ή στο Linux Documentation Project.


3. Νέες εκδόσεις, μεταφράσεις και διαθεσιμότητα

Η πιο πρόσφατη έκδοση μπορεί να βρεθέι στο http://tille.xalasys.com/training/bash/. Η ίδια έκδοση μπορεί να βρεθεί στο http://tldp.org/LDP/Bash-Beginners-Guide/html/index.html.

Ο οδηγός είναι διαθέσιμος σε έντυπη μορφή από το Fultus.com.

Εικόνα 1. Εξώφυλλο Bash Guide for Beginners

Εικόνα 1

Ο οδηγός έχει μεταφραστεί:

·         Στα Κινεζικά στο http://xiaowang.net/bgb-cn/, από Wang Wei.

·         Στα Ουκρανικά στο http://docs.linux.org.ua/index.php/LDP:Bash_beginners_guide, από τον Yaroslav Fedevych και την ομάδα του.

Προετοιμάζεται μια Γαλλική μετάφραση και θα αναρτηθεί σύντομα.

Η Ελληνική μετάφραση οφείλεται στον Κώστα Γ. Μαργαρίτη, στα πλαίσια της διδασκαλίας του μαθήματος Προγραμματισμός και Διαχείριση Συστημάτων ΙΙ, στο Τμήμα Εφαρμοσμένης Πληροφορικής του Πανεπιστημίου Μακεδονίας. Ειδικά ευχαριστώ τους φοιτητές του ακαδ. έτους 2006-7 για τις αρχικές προσπάθειες μετάφρασης.


4. Ιστορία αναθεωρήσεων

Revision History

Revision 1.8

2006-03-15

Revised by: MG

clarified example in Chap4, corrected here doc in chap9, general checks and correction of typos, added link to Chinese and Ukrainian translation, note and stuff to know about awk in chap6.

Revision 1.7

2005-09-05

Revised by: MG

Corrected typos in chapter 3, 6 and 7, incorporated user remarks, added a note in chap7.

Revision 1.6

2005-03-01

Revised by: MG

Minor debugging, added more keywords, info about new Bash 3.0, took out blank image.

Revision 1.5

2004-12-06

Revised by: MG

Changes because of new domain, minor corrections.

Revision 1.4

2004-10-18

Revised by: MG

Debugging, added a couple of notes in chap9, replaced screenshots with screen sections. Corrected some typos.

Revision 1.3

2004-07-09

Revised by: MG

Added tracer image 1x1 pixel http://tille.xalasys.com/images/blank-bash.png, added textobjects for all pictures, fixed wrong links in index, made signal list more clear.

Revision 1.2

2004-06-15

Revised by: MG

Added index, more markup in screen sections.

Revision 1.1

2004-05-22

Revised by: MG

Last read-through before going to press, added more examples, checked summaries, exercises, cleaned up introduction.

Revision 1.0

2004-04-27

Revised by: TM

Initial release for LDP; more exercises, more markup, less errors and abuse; added glossary.

Revision 1.0-beta

2003-04-20

Revised by: MG

Pre-release


5. Συνεισφορές

Ευχαριστω όλους τους φίλους που βοήθησαν (ή προσπάθησαν) και τον σύζυγό μου, του οποίου οι ενθαρρυντικά λόγια έκαναν τη δουλειά αυτή δυνατή. Ευχαριστώ όλους που έστειλαν αναφορές σφαλμάτων και άλλα σχόλια. Μεταξύ άλλων:

·         Hans Bol, ένας από τους οπαδούς

·         Mike Sim, σχόλια για το στυλ

·         Dan Richter, παραδείγματα πινάκων

·         Gerg Ferguson, ιδέες για τον τίτλο

·         Mendel Leo Cooper, για τον χώρο

·         #linux.be, γιατί με κρατά προσγειωμένη

·         Frank Wang, για τα λεπτομερή σχόλια για όλα που έκανα στραβά ;-)

Ειδικά ευχαριστώ τη Tabatha Marshall, που εθελοντικά έκανε μια πλήρη ανάγνωση και διόρθωση ορθογραφικών και γραμματικών σφαλμάτων. Κάνουμε πολύ καλή ομάδα: αυτή δουλεύει ενώ εγώ κοιμάμαι. Και αντιστρόφως ;-)


6. Ανάδραση

Σχόλια, πληροφορίες, σφάλαματ, ελλείψεις; Mail στο

<tille wants no spam _at_ xalasys dot com>


7. Πληροφορίες Copyright

Copyright © 2003-2005 Machtelt Garrels.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being "New versions of this document", "Contributions", "Feedback" and "Copyright information", with no Front-Cover Texts and no Back-Cover Texts. A copy of the license is included in Appendix B entitled "GNU Free Documentation License".

The author and publisher have made every effort in the preparation of this book to ensure the accuracy of the information. However, the information contained in this book is offered without warranty, either express or implied. Neither the author nor the publisher nor any dealer or distributor will be held liable for any damages caused or alleged to be caused either directly or indirectly by this book.

The logos, trademarks and symbols used in this book are the properties of their respective owners.


8. Τι χρειάζεστε;

Ο φλοιός bash διαθέσιμος στο http://www.gnu.org/directory/GNU/. Ο φλοιός bash βρίσκεται σχεδόν σε κάθε σύστημα Linux, και σε αρκετά συστήματα UNIX.

Μεταγλωττίζεται εύκολα, αν δεν το βρείτε προεγκατεστημένο, και έχει ελεγχθεί σε πολλά συστήματα UNIX, Linux, MS Windows και άλλα.


9. Συμβάσεις του κειμένου

Στο κείμενο ακολουθούνται οι παρακάτων τυπογραφικές συμβάσεις:

Πίνακας 1. Τυπογραφικές συμβάσεις

Τύπος κειμένου

Σημασία

"Κείμενο σε εισαγωγικά"

Αυτούσια μεταφορά κειμένου από πρόσωπα ή έξοδο υπολογιστή

έξοδος τερματικού

Ακριβής μεταφορά εισόδου και εξόδου τερματικού, συνήθως σε γκρίζο φόντο

εντολή

Όνομα εντολής όπως εισάγεται στη γραμμή εντολών

ΜΕΤΑΒΛΗΤΗ

Όνομα μεταβλητής ή δείκτης στο περιεχόμενο (τιμή) μεταβλητής, όπως στo $ΜΕΤΑΒΛΗΤΗ.

επιλογή

Επιλογή σε μια εντολή, όπως η "επιλογή -a στην εντολή ls".

όρισμα

Όρισμα εντολής, όπως "διαβάστε το man ls".

εντολή επιλογές ορίσματα

Σύνοψη γενικής χρήσης εντολής, σε ξεχωριστή γραμμή.

όνομα_αρχείου

Όνομα αρχείου ή καταλόγου, για παράδειγμα "Αλλαγή στον κατάλογο /usr/bin "

Πλήκτρο

Πλήκτρο του πληκτρολογίου, όπως "πιέστε Q για έξοδο".

Κουμπί

Γραφικό κουμπί για επιλογή (click), όπως το κουμπί OK.

Μενού->Επιλογή

Επιλογή από γραφικό μενού, λόγου χάρη: "Επιλέξτε Help->About Mozilla στο περιηγητή σας."

Ορολογία

Σημαντικός όρος ή έννοια: "Ο πυρήνας του Linux είναι η καρδιά του συστήματος."

\

Το backslash σε έξοδο τερματικού ή σε σύνοψη εντολής δηλώνει συνέχεια. Με άλλα λόγια, αν δείτε μια μεγάλη εντολή τεμαχισμένη σε πολλές γραμμές, το \ σημαίνει "Μη πιέσετε ακόμη Enter !"

Δείτε Κεφάλαιο 1

Σύνδεσμος σε σχετικό θέμα μέσα στο κείμενο.

Ο συγγραφέας

Σύνδεσμος σε εξωτερικό πόρο ιστού.


10. Οργάνωση του κειμένου

Αυτός ο οδηγός συζητά έννοιες που είναι χρήσιμες στη καθημερινή δραστηριότητα ενός σοβαρού χρήστη Bash. Ενώ η βασική χρήση του φλοιού είναι προαπαιτούμενη, ξεκινούμε με μια συζήτηση των βσικών συστατικών και πρακτικών του φλοιού, στα τρία πρώτα κεφάλαια.

Τα κεφάλαια τέσσερα έως έξι συζητούν τα βασικά εργαλεία που συνήθως χρησιμοποιούνται στα σενάρια φλοιού.

Τα κεφάλαια οκτώ έως δώδεκα συζητούν τις συνηθέστερες δομές των σεναρίων φλοιού.

Όλα τα κεφάλαια συνοδεύονται από ασκήσεις που εξετάζουν την ετοιμότητά σας για το επόμενο κεφάλαιο.

·         Κεφάλαιο 1: Τα βασικά του Bash: γιατί το Bash είναι τόσο καλό, δομικά τμήματα, πρώτες οδηγίες για την ανάπτυξη καλών σεναρίων.

·         Κεφάλαιο 2: Τα βασικά των σεναρίων: συγγραφή και εκσφαλμάτωση.

·         Κεφάλαιο 3: Το περιβάλλον του Bash: αρχεία ρύθμισης, μεταβλητές, αυτούσια εμφάνιση χαρακτήρων, σειρά επέκτασης φλοιού, ψευδώνυμα, επιλογές.

·         Κεφάλαιο 4: Κανονικές εκφράσεις: μια εισαγωγή.

·         Κεφάλαιο 5: Sed:εισαγωγή στον διορθωτή γραμμής sed.

·         Κεφάλαιο 6:Awk: εισγωγή στη γλώσσα προγραμματισμού awk.

·         Κεφάλαιο 7: Δηλώσεις υπο συνθήκη: δομές του Bash για έλεγχο συνθηκών.

·         Κεφάλαιο 8: Διαλογικά σενάρια: κάνοντας τα σενάρια φιλικά στο χρήστη, ανάγνωση εισόδου από το χρήστη.

·         Κεφάλαιο 9: Επαναληπτική εκτέλεση εντολών: δομές του Bash για αυτόματη εκτέλεση εντολών.

·         Κεφάλαιο 10: Προχωρημένες μεταβλητές: ορισμός τύοων μεταβλητών, εισαγωγή στους πίνακες μεταβλητών, πράξεις με μεταβλητές.

·         Κεφάλαιο 11: Συναρτήσεις: μια ειαγωγή.

·         Κεφάλαιο 12: Σύλληψη σημάτων: εισγωγή στη σηματοδοσία διεργασιών και στη παγίδευση σημάτων χρηστών.


Κεφάλαιο 1. Bash και σενάρια Bash

Σε αυτό το εισαγωγικό κεφάλαιο

·         Περιγράφουμε ορισμένους σηνήθεις φλοιούς

·         Τονίζουμε κάποια πλεονεκτήματα και χαρακτηριστικά του GNU Bash

  • Περιγράφουμε τα δομικά μέρη του φλοιού

·         Συζητούμε για αρχεία εκκίνησης του Bash

  • Βλέπουμε πως ο φλοιός εκτελεί εντολές

·         Αναφερόμαστε σε μερικά απλά παραδείγματα σεναρίων


1.1. Κοινά προγράμματα φλοιού

1.1.1. Γενικές λειτουργίες φλοιού

Το πρόγραμμα φλοιού των UNIX διερμηνεύει εντολές του χρήστη, που είτε πληκτρολογούνται άμεσα από τον χρήστη, είτε μπορούν να διαβαστούν από ένα αρχείο που ονομάζεται σενάριο φλοιού ή πρόγραμμα φλοιού. Τα σενάριαφλοιού είναι διερμηνευόμεα, όχι μεταγλωττιζόμενα. Ο φλοιός διαβάζει τις εντολές από το σενάριο μια προς μια και τις αναζητά στο σύστημα (βλέπε Ενότητα 1.2), ενώ ο μεταγλωττιστής μετατρέπει ένα πρόγραμμα σε γλώσσα μηχανής, ένα εκτελέσιμο αρχείο – που τότε μπορεί να χρησιμοποιηθεί σαν εντολή σε ένα σενάριο φλοιού.

Εκτός από το να περνάει εντολές στον πυρήνα, η κύρια αποστολή του φλοιού είναι να παρέχει ένα περιβάλλον χρήστη, που μπορεί να τροποποιηθεί χρησιμοποιώντας αρχεία κειμένου για τη ρύθμιση  του φλοιού.


1.1.2. Είδη φλοιών

Όπως οι άνθρωποι κατανοούν διαφορετικές γλώσσες και διαλέκτους, το UNIX προσφέρει συνήθως μια ποικιλία φλοιών:

·         sh ή Bourne φλοιός: ο γνήσιος φλοιός που χρησιμοποιείται ακόμα σε συστήματα UNIX και σε σχετικά με UNIX περιβάλλοντα. Είναι ο βασικός φλοιός, ένα μικρό πρόγραμμα με λίγα χαρακτηριστικά. Ενώ δεν είναι ο τυπικός φλοιός, είναι ακόμα διαθέσιμος σε κάθε σύστημα Linux για συμβατότητα με προγράμματα UNIX.

·         bash ή Bourne Again φλοιός: ο τυπικός GNU φλοιός, διαισθητικός και ευέλικτος. Πιθανόν η καλύτερη επιλογή για αρχάριους χρήστες ενώ είναι παράλληλα ένα πολύ ισχυρό εργαλείο για τον προχωρημένο και τον επαγγελματία χρήστη. Στα Linux, ο bash είναι ο τυπικός φλοιός για απλούς χρήστες. Αυτός ο φλοιός είναι το λεγόμενο υπέρ-πακέτο του φλοιού Bourne, ένα πακέτο με add-ons και plug-ins. Αυτό σημαίνει ότι ο Bourne Again φλοιός είναι συμβατός με τον φλοιό Bourne: εντολές που τρέχουν στον sh, τρέχουν επίσης στον bash. Ωστόσο, κρατείστε πάντα μια μικρή επιφύλαξη. Όλα τα παραδείγματα και οι ασκήσεις σε αυτό το βιβλίο χρησιμοποιούν τον bash.

·         csh ή C  φλοιός: η σύνταξη αυτού του φλοιού μοιάζει με αυτήν της γλώσσας προγραμματισμού C

·         tcsh ή Turbo C φλοιός: ένα υπέρ-πακέτο του κοινού C φλοιού, με βελτιώσεις στην φιλικότητα προς τον χρήστη και την ταχύτητα.

·         ksh ή Korn φλοιός: μερικές φορές εκτιμάται από ανθρώπους με υπόβαθρο UNIX. Ένα υπέρ-πακέτο του φλοιού Bourne, με την βασική προειδοποίηση οτι είναι ένας εφιάλτης για τους αρχάριους προγραμματιστές.

Το αρχείο /etc/shells δίνει μια σύνοψη των γνωστών φλοιών του συστήματος Linux:

 
mia:~> cat /etc/shells
/bin/bash
/bin/sh
/bin/tcsh
/bin/csh

Ο προεπιλεγμένος φλοιός βρίσκεται στο αρχείο /etc/passwd , όπως αυτή η γραμμή για την χρήστη Mia:

 

 
mia:L2NOfqdlPrHwE:504:504:Mia Maya:/home/mia:/bin/bash

Για να αλλάξετε από έναν φλοιό σε άλλον, απλώς εισάγετε το όνομα του νέου φλοιού στο ενεργό τερματικό. Το σύστημα βρίσκει τον κατάλογο στο οποίο παραπέμπει το όνομα χρησιμοποιώντας τις ρυθμίσεις PATH, και αφού ο φλοιός είναι ένα εκτελέσιμο αρχείο, ο τρέχων φλοιός τον ενεργοποιεί και εκτελείται. Συνήθως ένα διαφορετικό σύμβολο προτροπής εμφανίζεται, επειδή κάθε φλοιός έχει την δική του τυπική εμφάνιση:

 
mia:~> tcsh
[mia@post21 ~]$

1.2. Πλεονεκτήματα του φλοιού Bourne Again

1.2.1. Το Bash είναι ο GNU φλοιός

Το έργο GNU (GNU δεν είναι UNIX) παρέχει εργαλεία για διαχείριση συστημάτων τύπου UNIX τα οποία είναι ελεύθερο λογισμικό και σύμφωνα με τα πρότυπα του UNIX.

Το Bash είναι ένας sh-συμβατός φλοιός που ενσωματώνει χρήσιμα χαρακτηριστικά του φλοιού Korn (ksh) και του φλοιού C (csh). Είναι σύμφωνος με τον φλοιό ΙΕΕΕ POSIX Ρ1003.2/ISO 9945.2 και με τα πρότυπα εργαλεία (Tools). Προσφέρει λειτουργικές βελτιώσεις όχι μόνο για προγραμματιστική αλλά και για αλληλεπιδραστική χρήση. Αυτά περιλαμβάνουν επεξεργασία γραμμής εντολών, απεριόριστο μέγεθος ιστορικού εντολών, έλεγχο εργασιών, λειτουργίες φλοιού και ψευδώνυμα, πίνακες με δείκτες απείρου μεγέθους και αριθμητική ακεραίων σε κάθε βάση από το 2 μέχρι το 64. O Bash μπορεί να εκτελέσειι τα περισσότερα από τα σενάρια sh χωρίς τροποποίηση.

 

Όπως τα άλλα έργα GNU, το έργο bash διατηρεί, προστατεύει και προωθεί την ελευθερία στην χρήση, μελέτη, αντιγραφή, τροποποίηση και αναδιανομή λογισμικού. Είναι γενικά γνωστό ότι τέτοιες συνθήκες υποκινούν την δημιουργικότητα. Αυτό είναι επίσης αλήθεια και με το λογισμικό bash, το οποίο έχει πολλά επιπλέον χαρακτηριστικά τα οποία άλλοι φλοιοί δεν μπορούν να προσφέρουν.

 


1.2.2. Αποκλειστικά χαρακτηριστικά του φλοιού Bash

1.2.2.1. Κλήση

Αντίθετα με τις επιλογές γραμμής εντολών ενός μόνο χαρακτήρα, που μπορούν γενικά να τροποποιηθούν χρησιμοποιώντας την ενσωματωμένη εντολή φλοιού set, υπάρχουν αρκετές επιλογές πολλών χαρακτήρων που μπορείούμε να χρησιμοποιήσουμε. Θα βρεθούμε απέναντι σε κάποιες από τις πιο γνωστές επιλογές σε αυτό και στα επόμενα κεφάλαια. Η ολοκληρωμένη λίστα υπάρχει στις σελίδες πληροφοριών του φλοιού Bash, χαρακτηριστικά του Bash->Κλήση Bash.


1.2.2.2. Αρχεία εκκίνησης του Bash

Τα αρχεία εκκίνησης είναι σενέρια που διαβάζονται και εκτελούνται από το Bash όταν ξεκινάει. Οι επόμενες υποενότητες περιγράφουν διάφορους τρόπους εκκίνησης του φλοιού, και των αρχείων εκκίνησης τα οποία διαβάζονται διαδοχικά.

 


1.2.2.2.1. Κλήση διαλογικού φλοιού σύνδεσης, ή κλήση με '--login'

Διαλογικός φλοιός σημαίνει ότι μπορούμε να εισάγουμε εντολές. Ο φλοιός δεν εκτελείται επειδή έχει ενεργοποιηθεί ένα σενάριο αλλά λόγω σύνδεσης ενός χρήστη. Ένας φλοιός σύνδεσης σημαίνει ότι έχουμε ξεκινήσει τον φλοιό μετά από την ταυτοποίησή μας από το σύστημα, συνήθως δίνοντας το όνομα χρήστη και τον κωδικό πρόσβασης.

Ανάγνωση αρχείων:

·         /etc/profile

·         ~/.bash_profile, ~/.bash_login ή ~/.profile: διαβάζεται το πρώτο αναγνώσιμο αρχείο που υπάρχει

·         ~/.bash_logout στην αποσύνδεση.

Μηνύματα σφάλματος εκτυπώνονται αν τα αρχεία διαμόρφωσης υπάρχουν αλλά δεν είναι αναγνώσιμα. Αν ένα αρχείο δεν υπάρχει, το bash ψάχνει για το επόμενο.

 


1.2.2.2.2. Κλήση διαλογικού φλοιού μη-σύνδεσης

Ένας φλοιός μη-σύνδεσης σημαίνει ότι δεν απαιτείται ταυτοποίηση από το σύστημα. Για παράδειγμα, όταν ανοίγουμε ένα τερματικό χρησιμοποιώντας ένα εικονίδιο, ή ένα αντικείμενο menu, αυτός είναι ο φλοιός μη-σύνδεσης.

Ανάγνωση αρχείων:

·         ~/.bashrc

Αυτό το αρχείο συνήθως αναφέρεται στο ~/.bash_profile:

if [ -f ~/.bashrc ]; then . ~/.bashrc; fi

Βλέπε Κεφάλαιο 7 για περισσότερες πληροφορίες σχετικά με την δομή if.


1.2.2.2.3. Μη-διαλογική κλήση

Όλα τα σενάρια χρησιμοποιούν μη-διαλογικούς φλοιούς. Είναι προγραμματισμένα να εκτελέσουν ορισμένες εργασίες και δεν μπορούν να καθοδηγηθούν στο να κάνουν άλλες δουλειές παρά μόνο αυτές για τις οποίες έχουν προγραμματιστεί.

Ανάγνωση αρχείων:

·         καθορίζεται από τη μεταβλητή BASH_ENV

Η PATH δεν χρησιμοποιείται για την αναζήτηση αυτού του αρχείου, έτσι αν θέλετε να το χρησιμοποιήσετε, καλύτερα αναφερθείτε σε αυτό δίνοντας ολόκληρη την διαδρομή και το όνομα του αρχείου.

 


1.2.2.2.4. Κλήση με την εντολή sh

Το Bash προσπαθεί να συμπεριφέρεται σαν το ιστορικό Bourne sh πρόγραμμα ενώ παράλληλα προσαρμόζεται στο POSIX πρότυπο.

Ανάγνωση αρχείων:

·         /etc/profile

·         ~/.profile

Όταν η κλήση είναι διαλογική , η μεταβλητή ΕΝV μπορεί να δείξει επιπλέον πληροφορίες εκκίνησης.


1.2.2.2.5. Κατάσταση POSIX

Αυτή η επιλογή ενεργοποιείται είτε χρησιμοποιώντας την ενσωματωμένη εντολή set:

set -o posix

είτε καλώντας το πρόγραμμα bash με την --posix επιλογή. Το Bash τότε θα προσπαθήσει να συμπεριφερθεί όσο το δυνατό σύμφωνα με το POSIX πρότυπο για φλοιούς. Θέτοντας την POSIXLY_CORRECT μεταβλητή πετυχαίνουμε το ίδιο.

Ανάγνωση αρχείων:

·         καθορίζεται από τη μεταβλητή ENV.


1.2.2.2.6. Απομακρυσμένη κλήση

Ανάγνωση αρχείων όταν ο φλοιός καλείται με rshd:

·         ~/.bashrc

Warning

Αποφυγή χρήσης των r-εργαλείων

 

Προσοχή στους κινδύνους της χρήσης εργαλείων όπως rlogin, telnet, rsh και rcp. Είναι εντελώς ανασφαλή επειδή εμπιστευτικά δεδομένα στέλνονται μέσω του δικτύου χωρίς να κρυπτογραφηθούν. Αν χρειάζεστε εργαλεία για απομακρυσμένη εκτέλεση, μεταφορά αρχείων κ.α., χρησιμοποίησε μια εφαρμογή του Secure SHell, γενικώς γνωστός ως SSH, ο οποίος διατίθεται ελεύθερα από την http://www.openssh.org. Διαφορετικά προγράμματα πελάτη είναι διαθέσιμα για μη-UNIX συστήματα επίσης, δείτε στο τοπικό σας αποθετήριο λογισμικού.


1.2.2.2.7. Κλήση όταν το UID δεν είναι ίσο με το EUID

Στην περίπτωση αυτή δεν διαβάζονται αρχεία εκκίνησης.


1.2.2.3. Διαλογικοί φλοιοί 

1.2.2.3.1. Τι είναι ένας διαλογικός φλοιός;

Ένας διαλογικός φλοιός συνήθως διαβάζει από, και γράφει σε, ένα τερματικό χρήστη: η πρότυπη είσοδος και έξοδος είναι συνδεδεμένες σε ένα τερματικό. Η διαλογική συμπεριφορά του Bash ξεκινάει όταν η εντολή bash καλείται χωρίς άλλα ορίσματα παρά μόνο με επιλογές, εκτός από την περίπτωση που η επιλογή είναι μια συμβολοσειρά από όπου πρέπει να διαβάσει ο φλοιός ή όταν ο φλοιός έχει κληθεί να διαβάσει από πρότυπη είσοδο, η οποία επιτρέπει σε παραμέτρους θέσης να οριστούν (βλέπε Κεφάλαιο 3 ).


1.2.2.3.2. Είναι αυτός ο φλοιός διαλογικός;

Δοκίμασε το κοιτάζοντας το περιεχόμενο της ειδικής παραμέτρου -, η οποία περιέχει ένα 'i' όταν ο φλοιός είναι διαλογικός:

 
eddy:~> echo $-
himBH

Σε μη-διαλογικούς φλοιούς, η προτροπή PS1 δεν είναι ορισμένη.


1.2.2.3.3. Συμπεριφορά διαλογικού φλοιού

Διαφορές στην διαλογική κατάσταση:

·         Ο Bash διαβάζει αρχεία εκκίνησης.

·         Ο έλεγχος εργασιών είναι προεπιλογμένος.

·         Ορίζονται οι προτροπές, η PS2 ενεργοποιείται για εντολές πολλών γραμμών, και είναι συνήθως ορισμένη σε ">". Αυτή είναι επίσης η προτροπή που λαμβάνουμε όταν ο φλοιός θεωρεί ότι εισάγουμε μια ανολοκλήρωτη εντολή, για παράδειγμα όταν ξεχνάμε εισαγωγικά, δομές εντολών που δεν μπορούν να παραλειφθούν κτλ.

·         Οι εντολές διαβάζονται από την γραμμή εντολών με την readline (προεπιλογή).

·         Το Bash διερμηνεύει την επιλογή φλοιού ignoreeof αντί να τερματίζεται αμέσως μόλις λάβει  EOF (End Of File).

·         Το ιστορικό εντολών και οι επεκτάσεις ιστορικού είναι ενεργοποιημένες ως προεπιλογή. Το ιστορικό αποθηκεύεται στο αρχείο που υποδεικνύει η HISTFILE όταν κλείνει ο φλοιός. Ως προεπιλογή, η HISTFILE υποδεικνύει το ~/.bash_history.

·         Η επέκταση ψευδωνύμων είναι ενεργοποιημένη.

·         Αν δεν υπάρχουν παγίδες (traps), το SIGTERM σήμα αγνοείται.

·         Αν δεν υπάρχουν παγίδες (traps), το SIGINT ανιχνεύεται και υφίσταται διαχείριση. Έτσι, πατώντας Ctrl+C, για παράδειγμα, ο διαλογικός φλοιός δεν τερματίζεται.

·         Η αποστολή SIGHUP σημάτων σε όλες τις εργασίες κατά την αποσύνδεση ρυθμίζεται με την επιλογή huponexit.

·         Οι εντολές εκτελούνται μόλις διαβαστούν.

·         Το Bash ελέγχει περιοδικά για αλληλογραφία.

·         Το Bashμπορεί να ρυθμιστεί ώστε να τερματίζεται όταν αντιμετωπίζει μεταβλητές που δεν έχουν οριστεί. Στην διαλογική αυτή η συμπεριφορά είναι απενεργοποιημένη.

·         Όταν οι εσωτερικές εντολές του φλοιού αντιμετωπίζουν σφάλματα ανακατεύθυνσης, ο φλοιός δεν αναγκάζεται να τερματιστεί.

·         Σφάλματα που επιστρέφονται από εντολές που χρησιμοποιούνται σε κατάσταση POSIX δεν αναγκάζουν τον φλοιό να τερματιστεί. Οι εσωτερικές εντολές παρουσιάζονται στην Ενότητα 1.3.

·         Αποτυχία του exec δεν θα τερματίσει τον φλοιό.

·         Λανθασμένη συντακτική ανάλυση δεν αναγκάζει τον φλοιό να τερματιστεί.

·         Προεπιλεγμένος απλός ορθογραφικός έλεγχος για τα ορίσματα στην εσωτερική εντολή cd.

·         Ενεργοποίηση αυτόματης εξόδου μετά την πάροδο του χρόνου που ορίστηκε στην μεταβλητή TMOUT.

Περισσότερες πληροφορίες:

·         Ενότητα 3.2

·         Ενότητα 3.6

·         Δείτε Κεφάλαιο 12 για περισσότερα σχετικά με τα σήματα.

·         Η Ενότητα 3.4αναφέρεται στις διάφορες επεκτάσεις που εκτελούνται κατά την εισαγωγή μιας εντολής.


1.2.2.4. Συνθήκες

Οι  εκφράσεις υπό συνθήκη χρησιμοποιούνται από την σύνθετη εντολή [[ και από τις εσωτερικές εντολές test και [.

Οι εκφράσεις μπορούν να  είναι μοναδιαίες ή δυαδικές. Οι μοναδιαίες εκφράσεις συνήθως χρησιμοποιούνται για να εξετάσουν την κατάσταση ενός αρχείου. Απαιτείται μόνο ένα αντικείμενο, για παράδειγμα ένα αρχείο, για να λειτουργήσει η διαδικασία.

Υπάρχουν αλφαριθμητικοί τελεστές αλλά και συγκριτικοί αριθμητικοί τελεστές επίσης: αυτοί είναι δυαδικοί τελεστές, χρειάζονται δυο αντικείμενα για την διαδικασία. Αν το όρισμα FILE σε ένα από τα μέλη της συνθήκης είναι της μορφής /dev/fd/N, τότε ελέγχεται ο περιγραφέας αρχείου N. Αν το όρισμα FILE σε ένα από τα μέλη της συνθήκης είναι της μορφής /dev/stdin, /dev/stdout ή /dev/stderr, τότε ελέγχεται ο περιγραφέας αρχείου 0, 1 ή 2.

Οι συνθήκες παρουσιάζονται λεπτομερειακά στο Κεφάλαιο 7.

Περισσότερες πληροφορίες σχετικά με τους περιγραφείς αρχείου στην Ενότητα 8.2.3.


1.2.2.5. Αριθμητική φλοιού

Ο φλοιός επιτρέπει την αποτίμηση αριθμητικών εκφράσεων, είτε μέσω μιας από της επεκτάσεις φλοιού ή μέσω της εσωτερικής εντολής let.

Η αποτίμηση εκτελείται σε ακεραίους σταθερού εύρους χωρίς έλεγχο για υπερχείλιση, ωστόσο η διαίρεση με το 0 ανιχνεύεται και σημειώνεται ως σφάλμα. Οι τελεστές και η προτεραιότητα και η προτεραιότητά τους  είναι ίδια με την γλώσσα C, βλέπε Κεφάλαιο 3.


1.2.2.6. Ψευδώνυμα

Τα ψευδώνυμα επιτρέπουν σε ένα αλφαριθμητικό να υποκαθίσταται από ένα άλλο όταν χρησιμοποιείται ως η πρώτη λέξη μιας απλής εντολής. Ο φλοιός διατηρεί την λίστα των ψευδωνύμων που μπορεί να ενεργοποιηθεί ή να απενεργοποιηθεί με τις alias και unalias εντολές.

Το Bash πάντα διαβάζει τουλάχιστον μια ολόκληρη γραμμή εισόδου πριν εκτελέσει οποιαδήποτε από τις εντολές σε αυτή τη γραμμή. Τα ψευδώνυμα επεκτείνονται όταν διαβάζεται μια εντολή, όχι όταν εκτελείται. Επομένως, ένας ορισμός ψευδωνύμου που εμφανίζεται στην ίδια γραμμή με μια άλλη εντολή δεν εφαρμόζεται μέχρι να διαβαστεί η επόμενη γραμμή εισόδου. Οι εντολές που ακολουθούν τον καθορισμό των ψευδωνύμων σε αυτή την γραμμή δεν επηρεάζονται από τα καινούρια ψευδώνυμα.

Τα ψευδώνυμα επεκτείνονται όταν διαβάζεται ένας ορισμός συνάρτησης, όχι όταν μια συνάρτηση εκτελείται, επειδή ο ορισμός συνάρτησης είναι από μόνος του μια σύνθετη εντολή. Ως συνέπεια, τα ψευδώνυμα που ορίζονται σε μια συνάρτηση δεν είναι διαθέσιμα πριν την εκτέλεση της συνάρτησης.

Θα εξετάσουμε λεπτομερώς τα ψευδώνυμα στην Ενότητα 3.5.


1.2.2.7. Πίνακες

Το Bash παρέχει μεταβλητές μονοδιάστατου πίνακα. Κάθε μεταβλητή μπορεί να χρησιμοποιηθεί σαν πίνακας: η εσωτερική εντολή declare δηλώνει ρητά έναν πίνακα. Δεν υπάρχει ανώτατο όριο στο μέγεθος ενός πίνακα, ούτε καμία απαίτηση τα μέλη να εισάγονται ή να ορίζονται συνεχόμενα. Οι πίνακες έχουν ως βάση το 0. Βλέπε Κεφάλαιο 10.


1.2.2.8. Στοίβα καταλόγων

Η στοίβα καταλόγων είναι μια λίστα των πρόσφατα προσπελασμένων καταλόγων. Η εσωτερική εντολή pushd προσθέτει καταλόγους στη στοίβα καθώς αλλάζει ο τρέχων κατάλογος, και η εσωτερική εντολή popd αφαιρεί καταλόγους από την στοίβα και αλλάζει τον τρέχοντα κατάλογο με τον κατάλογο που αφαίρεσε.

Το περιεχόμενο μπορεί να προβληθεί χρησιμοποιώντας την εντολή dirs ή ελέγχοντας το περιεχόμενο της μεταβλητής DIRSTACK.

Περισσότερες πληροφορίες σχετικά με την λειτουργία αυτού του μηχανισμού βρίσκονται στις σελίδες πληροφοριών για το Bash.


1.2.2.9. Η προτροπή

Το Bash κάνει το παιχνίδι με την προτροπή ακόμα πιο διασκεδαστικό. Βλέπε την ενότητα Ελέγχοντας την προτροπή στις σελίδες πληροφοριών για τον Bash.


1.2.2.10. Ο περιορισμένος φλοιός

Όταν καλείται ως rbash ή με την επιλογή --restricted ή -r, συμβαίνουν τα ακόλουθα:

·         Η εσωτερική εντολή cd είναι απενεργοποιημένη.

·         Η ρύθμιση των μεταβλητών SHELL, PATH, ENV or BASH_ENV δεν είναι δυνατή.

·         Τα ονόματα των εντολών δεν μπορούν πλέον να περιέχουν slash (/).

·         Ονόματα αρχείων που περιέχουν '/' δεν γίνονται δεκτά με την εσωτερική εντολή . (source).

·         Η εσωτερική εντολή hash δεν αποδέχεται το '/'με την επιλογή -p.

·         Η εισαγωγή συναρτήσεων στην εκκίνηση δεν επιτρέπεται.

·         Κατά την εκκίνηση αγνοείτα η μεταβλητή SHELLOPTS.

·         Η επανακατεύθυνση της εξόδου χρησιμοποιώντας  >, >|, ><, >&, &> and >> είναι απενεργοποιημένη.

·         Η εσωτερική εντολή exec είναι απενεργοποιημένη.

·         Οι -f και -dεπιλογές είναι απενεργοποιημένες για την εσωτερική εντολή enable.

·         Η εσωτερική εντολή command δεν μπορεί να προσδιορίσει ένα προεπιλεγμένο PATH.

·         Δεν είναι δυνατή η απενεργοποίηση της περιορισμένης λειτουργίας.

Όταν εκτελείται μια εντολή που τυχαίνει να είναι ένα σενάριο φλοιού, η rbash απενεργοποιεί οποιουσδήποτε περιορισμούς στον φλοιό ώστε να εκτελέσει το σενάριο.

Περισσότερες πληροφορίες:

·         Ενότητα 3.2

·         Ενότητα 3.6

·         Πληροφορίες Bash->Βασικά χαρακτηριστικά του Bash->Ανακατευθύνσεις

·         Ενότητα 8.2.3: προχωρημένες ανακατευθύνσεις.


1.3. Εκτέλεση εντολών

1.3.1. Γενικά

Το Bashκαθορίζει τον τύπο προγράμματος που πρόκειται να εκτελεστεί. Τα κανονικά προγράμματα είναι εντολές συστήματος που υπάρχουν σε μεταγλωττισμένη μορφή στο σύστημα. Όταν ένα τέτοιο πρόγραμμα εκτελείται, δημιουργείται μια νέα διεργασία καθώς το Bash κάνει ένα ακριβές αντίγραφο του εαυτού του. Αυτή η θυγατρική διεργασία έχει το ίδιο περιβάλλον με την γονική διεργασία της, μόνο που ο αριθμός PID της διεργασίας είναι διαφορετικός. Αυτή η διαδικασία ονομάζεται forking (διακλάδωση).

Μετά τη διακλάδωση, ο χώρος διευθύνσεων της θυγατρικής διεργασίας εγγράφεται με τα νέα δεδομένα της διεργασίας. Αυτό γίνεται μέσω της κλήσης της exec από το σύστημα.

Έτσι ο μηχανισμός  fork-and-exec αλλάζει μια παλιά εντολή με μια καινούρια, όταν το περιβάλλον στο οποίο το καινούριο πρόγραμμα εκτελείται παραμένει το ίδιο, περιλαμβανομένων των ρυθμίσεων των συσκευών εισόδου και εξόδου,  των μεταβλητών περιβάλλοντος και της προτεραιότητας. Αυτός ο μηχανισμός συνηθίζεται να δημιουργεί όλες τις διεργασίες UNIX, πράγμα που ισχύει επίσης και στο Linux. Ακόμη και η πρώτη επεξεργασία, init, με αριθμό PID 1, διακλαδίζεται κατά τη διάρκεια της διαδικασίας εκκίνησης στo λεγόμενo bootstrapping.


1.3.2. Εσωτερικές εντολές φλοιού

Οι εσωτερικές (ενσωματωμένες) εντολές περιέχονται μέσα στον φλοιό. Όταν το όνομα μιας εσωτερικής εντολής χρησιμοποιείται σαν την πρώτη λέξη μιας απλής εντολής, ο φλοιός εκτελεί την εντολή άμεσα, χωρίς να δημιουργήσει μια καινούρια διεργασία. Οι εσωτερικές εντολές είναι απαραίτητες για την υλοποίηση λειτουργιών που θα ήταν ασύμφορο ή αδύνατο να υλοποιηθούν με εξωτερικές εντολές.

Το Bash υποστηρίζει 3 τύπους εσωετρικών εντολών:

·         Εσωτερικές εντολές φλοιού Bourne:

:, ., break, cd, continue, eval, exec, exit, export, getopts, hash, pwd, readonly, return, set, shift, test, [, times, trap, umask και unset.

·         Εσωτερικές εντολές φλοιού Bash:

alias, bind, builtin, command, declare, echo, enable, help, let, local, logout, printf, read, shopt, type, typeset, ulimit και unalias.

·         Ειδικές εσωτερικές εντολές:

Όταν το Bash εκτελείται σε κατάσταση POSIX , οι ειδικές εσωτερικές εντολές διαφέρουν από άλλες εσωτερικές εντολές σε τρία σημεία:

1.      Οι ειδικές εσωτερικές εντολές προηγούνται των συναρτήσεων φλοιού κατά την αναζήτηση εντολών.

2.      Αν μια ειδική εσωτερική εντολή επιστρέφει μήνυμα λάθους, ένας μη-διαλογικός φλοιός τερματίζεται.

3.      Εντολές εκχώρησης που προηγούνται της εντολής μένουν σε λειτουργία στο περιβάλλον του φλοιού μετά την ολοκλήρωση της εντολής.

Οι ειδικές εσωτερικές εντολές του POSIX είναι :, ., break, continue, eval, exec, exit, export, readonly, return, set, shift, trap και unset.

Οι περισσότερες από αυτές τις εσωτερικές εντολές θα συζητηθούν σε επόμενα κεφάλαια. Για τις εντολές που δεν συζητούνται, αναφερθείτε στις σελίδες πληροφοριών.


1.3.3. Εκτέλεση προγράμματος από ένα σενάριο

Όταν το πρόγραμμα που εκτελείται είναι ένα σενάριο φλοιού, το Bash δημιουργεί μια καινούρια διεργασία bash χρησιμοποιώντας μια διακλάδωση (fork). Αυτός ο υποφλοιός διαβάζει τις γραμμές από το σενάριο φλοιού, μια κάθε φορά. Οι εντολές σε κάθε γραμμή διαβάζονται, διερμηνεύονται και εκτελούνται σαν να είχαν έρθει κατευθείαν από το πληκτρολόγιο.

Όταν ο υποφλοιός επεξεργάζεται κάθε γραμμή του σεναρίου, ο γονικός φλοιός περιμένει την επεξεργασία του θυγατρικού φλοιού να τελειώσει. Όταν πλέον δεν υπάρχουν άλλες γραμμές προς ανάγνωση στο σενάριο, ο υποφλοιός τερματίζεται. Ο γονικός φλοιός ενεργοποιείται και εμφανίζει μια καινούρια προτροπή.


1.4. Δομικά μέρη

1.4.1. Δομικά μέρη φλοιού

1.4.1.1. Σύνταξη φλοιού

Αν η είσοδος δεν είναι σχολιασμένη, ο φλοιός την διαβάζει και την διαιρεί σε τελεστές και λέξεις, υιοθετώντας κανόνες αναφοράς (quoting) για να προσδιορίσει το νόημα κάθε χαρακτήρα εισόδου. Κατόπιν  οι λέξεις και οι τελεστές μεταφράζονται σε εντολές και άλλες δομές, που επιστρέφουν μια κατάσταση εξόδου (exit status) διαθέσιμη για διερεύνηση ή επεξεργασία. Το παραπάνω fork-and-exec σχέδιο εφαρμόζεται μόνο αφού ο φλοιός έχει αναλύσει την είσοδο με τον ακόλουθο τρόπο:

·         Ο φλοιός διαβάζει την είσοδό του από ένα αρχείο, από ένα αλφαριθμητικό ή από ένα τερματικό χρήστη.

·         Η είσοδος διαχωρίζεται σε λέξεις και τελεστές, υπακούοντας τους κανόνες αναφοράς, βλέπε Κεφάλαιο 3. Αυτά τα σύμβολα (tokens) διαχωρίζονται με μεταχαρακτήρες. Η επέκταση των ψευδωνύμων εκτελείται.

·         Ο φλοιός σαρώνει  (αναλύει και αντικαθιστά) τα σύμβολα με απλές και σύνθετες εντολές.

·         Το Bash εκτελεί διάφορες επεκτάσεις φλοιού, αναλύοντας τα επεκταμένα σύμβολα σε λίστες με ονόματα αρχείων, εντολές και ορίσματα.

·         Η ανακατεύθυνση εκτελείτε αν είναι απαραίτητο, ενώ οι τελεστές και οι τελεσταίοι τους αφαιρούνται από την λίστα ορισμάτων.

·         Οι εντολές εκτελούνται.

·         Προαιρετικά ο φλοιός αναμένει την ολοκλληρωση της εντολής και συλλέγει τη κατάσταση εξόδου.


1.4.1.2. Εντολές φλοιού

Μια απλή εντολή φλοιού όπως touch file1 file2 file3 αποτελείται από την ίδια την εντολή ακολουθούμενη από ορίσματα, χωρισμένα με κενά.

Ποιο πολύπλοκες εντολές φλοιού αποτελούνται από απλές εντολές τοποθετούμενες μαζί με διάφορες μεθόδους: σε μια σωλήνωση (pipeline) στην οποία η έξοδος μιας εντολής γίνεται η είσοδος μιας άλλης, σε μια επαναληπτική δομή ή δομή συνθήκης , ή σε κάποια άλλη ομαδοποίηση. Μερικά παραδείγματα:

ls | more

gunzip file.tar.gz | tar xvf -


1.4.1.3. Συναρτήσεις φλοιού

Οι συναρτήσεις φλοιού αποτελούν ένα τρόπο ομαδοποίησης εντολών για μελλοντική εκτέλεση χρησιμοποιώντας ένα απλό όνομα για την ομάδα. Εκτελούνται σαν μια απλή εντολή. Όταν το όνομα της διαδικασίας φλοιού χρησιμοποιείται σαν ένα απλό όνομα εντολής, η λίστα των εντολών που σχετίζεται με το όνομα της συνάρτησης εκτελείται.

Οι συναρτήσεις φλοιού εκτελούνται στα τρέχοντα συμφραζόμενα φλοιού; καμία καινούρια διεργασία δεν δημιουργείται για να τις διερμηνεύσει.

Οι συναρτήσεις εξηγούνται στο Κεφάλαιο 11.


1.4.1.4. Παράμετροι φλοιού

Η παράμετρος είναι μια οντότητα που αποθηκεύει τιμές. Μπορεί να είναι ένα όνομα, ένας αριθμός ή μια ειδική τιμή. Για τον σκοπό του φλοιού, η μεταβλητή είναι μια παράμετρος που αποθηκεύει ένα όνομα. Η μεταβλητή έχει μια τιμή και κάποια χαρακτηριστικά. Οι μεταβλητές δημιουργούνται με την εσωτερική εντολή declare.

Αν δεν δοθεί τιμή, η μεταβλητή δέχεται το κενό αλφαριθμητικό. Οι μεταβλητές μπορούν μόνο να διαγραφούν με την εσωτερική εντολή unset.

Η ανάθεση τιμών σε μεταβλητές παρουσιάζεται στην Ενότητα 3.2, η προχωρημένη χρήση των μεταβλητών στο Κεφάλαιο 10.


1.4.1.5. Επεκτάσεις φλοιού

Η επέκταση φλοιού πραγματοποιείται όταν κάθε γραμμή εντολής έχει χωριστεί σε σύμβολα (tokens). Oι επεκτάσεις που πραγματοποιούντα είναι:

·         Επέκταση παρενθέσεων

·         Επέκταση tilde (~)

·         Επέκταση παραμέτρων και μεταβλητών

·         Αντικατάσταση εντολών

·         Αριθμητική επέκταση

·         Διαχωρισμός λέξεων

·         Επέκταση ονομάτων αρχείων

Θα συζητήσουμε αυτές τις επεκτάσεις λεπτομερειακά στην Ενότητα 3.4.


1.4.1.6. Ανακατευθύνσεις

Πριν την εκτέλεση μιας εντολής, η είσοδος και έξοδός της μπορεί να ανακατευθυνθούν χρησιμοποιώντας μια ειδική σήμανση διερμηνευμένη από τον φλοιό. Η ανακατε'υθυνση μπορεί επίσης να χρησιμοποιηθεί για άνοιγμα και κλείσιμο αρχείων στο τρέχον περιβάλλον εκτέλεσης  του φλοιού.


1.4.1.7. Εκτέλεση εντολής

Όταν εκτελείται μια εντολή, οι λέξεις που η σάρωση έχει σημειώσει σαν τιμές μεταβλητών (πριν το όνομα της εντολής,) καθώς καιι οι ανακατευθύνσεις, αποθηκεύονται για μελλοντική αναφορά. Λέξεις που δεν είναι τιμές μεταβλητών ή ανακατευθύνσεις επεκτείνονται; η πρώτη απομένουσα λέξη μετά την επέκταση λαμβάνεται ως το όνομα της εντολής και η τα υπόλοιπα ως ορίσματα σε αυτή την εντολή. Τότε λειτουργούν οι ανακατευθύνσεις,και  τα αλφαριθμητικά που έχουν θεωρηθεί τιμές μεταβλητών επεκτείνονται. Αν δεν προκύψει κάποιο όνομα εντολής, οι μεταβλητές θα επηρεάσουν το τρέχον περιβάλλον του φλοιού.

Ένα σημαντικό μέρος της εργασίας του φλοιού είναι να αναζητά εντολές. Το Bash το υλοποιεί ως εξής:

·         Ελέγχει αν η εντολή περιέχει κόμματα. Αν όχι, πρώτα ελέγχει την λίστα συναρτήσεων για να δει αν περιέχει μια εντολή με το όνομα που ψάχνουμε.

·         Αν η εντολή δεν είναι μια συνάρτηση, ελέγχει για αυτήν στην λίστα των εσωτερικών εντολών.

·         Αν η εντολή δεν είναι συνάρτηση ή εσωτερική εντολή, τότε η αναζήτηση συνεχίζεται στους καταλόγους της μεταβλητής PATH. Το Bash χρησιμοποιεί ένα hash table (πίνακας κατακερματισμού) για να θυμάται τα πλήρη ονόματα διαδρομών των εκτελέσιμων και έτσι οι αναζητήσεις μέσω της PATH ς μππορεί να μειωθούν.

·         Αν η αναζήτηση είναι ανεπιτυχής, το Bash εμφανίζει ένα μήνυμα σφάλματος και τη κατάσταση εξόδου 127.

·         Αν η αναζήτηση είναι επιτυχής ή αν η εντολή περιέχει κόμματα, ο φλοιός εκτελεί την εντολή σε ξεχωριστό περιβάλλον εκτέλεσης.

·         Αν η εκτέλεση αποτύχει επειδή ότι το αρχείο δεν είναι εκτελέσιμο και δεν είναι κατάλογος, τότε το Bash υποθέτει ότι είναι ένα σενάριο φλοιού.

·         Αν η εντολή δεν ξεκίνησε ασύγχρονα, ο φλοιός περιμένει την εντολή να ολοκληρωθεί και συλλέγει την κατάσταση εξόδου.


1.4.1.8. Σενάρια φλοιού

Αν το Bash κληθεί με το πρώτο όρισμα μετά τις επιλογές είναι ένα όνομα αρχείου, τότε ο φλοιός υποθέτει οτι πρόκειται για σενάριο φλοιού.  (Αν κληθεί με επιλογή -c ή -s, αυτό θα δημιουργήσει έναν μη-διαλογικό φλοιό). Ο φλοιός πρώτα αναζητά το σενάριο στον τρέχοντα κατάλογο,  και αν το αρχείο δεν μπορεί να βρεθεί εκεί αναζητά το αρχέιο μέσω της PATH.


1.5. Ανάπτυξη καλών σεναρίων

1.5.1. Ιδιότητες καλών σεναρίων

Αυτός ο οδηγός αναφέρεται κυρίως στο τελευταίο δομικό μέρος του φλοιού, τα σενάρια. Μερικές γενικές σκέψεις πριν συνεχίσουμε:

1.      Ένα σενάριο θα πρέπει να εκτελέιται χωρίς λάθη.

2.      Θα πρέπει να φέρει εις πέρας τον σκοπό για τον οποίο προορίζεται.

3.      Η λογική του προγράμματος είναι αυστηρά καθορισμένη και εμφανής.

4.      Ένα σενάριο δεν κάνει δουλειά που δεν είναι απαραίτητη.

5.      Τα σενάρια πρέπει να είναι επαναχρησιμοποιήσιμα.


1.5.2. Δομή

Η δομή ενός σεναρίου φλοιού είναι πολύ ευέλικτη. Αν και στο Bash υπάρχει μεγάλη ελευθερία, πρέπει διασφαλίζεται η σωστή λογική, ο έλεγχος ροής και αποδοτικότητα έτσι ώστε οι χρήστες που εκτελούν το σενάριο να μπορούν να το κάνουν εύκολα και σωστά.

Όταν ξεκινάτε σε ένα νέο σενάριο, ρωτήστε τον εαυτό σας τις ακόλουθες ερωτήσεις:

·         Θα χρειαστώ πληροφορίες από τον χρήστη ή από το περιβάλλον του χρήστη;

·         Πώς θα αποθηκεύσω αυτές τις πληροφορίες;

·         Υπάρχουν αρχεία που πρέπει να δημιουργηθούν; Πού και με τι άδειες και ιδιοκτησίες;

·         Τι εντολές θα χρησιμοποιήσω; Όταν χρησιμοποιώ ένα σενάριο σε διαφορετικά συστήματα, έχουν όλα αυτά τα συστήματα τις εντολές στην απαραίτητη έκδοση;

·         Χρειάζεται ο χρήστης κάποια πληροφορία; Πότε και γιατί;


1.5.3. Ορολογία

Ο παρακάτω πίνακας δίνει μια σύνοψη προγραμματιστικών όρων με τους οποίους πρέπει να είστε εξοικειωμένοι:

Πίνακας 1-1. Σύνοψη προγραμματιστικών όρων

Όρος

Τι είναι;

Έλεγχος εντολών

Δοκιμή της κατάστασης  εξόδου με σκοπό να εξακριβώσουμε αν το συγκεκριμένο τμήμα του προγράμματος θα εκτελεστεί σωστά

Διακλάδωση υπό συνθήκη

Λογικό σημείο στο πρόγραμμα όταν μια συνθήκη καθορίζει τι γίνεται στην συνέχεια.

Λογική ροή

Το γενικό σχέδιο του προγράμματος. ΕΚαθορίζει μια λογική ακολουθία στόχων έτσι ώστε το αποτέλεσμα να είναι επιτυχημένο και ελεγχόμενο.

Βρόχος

Μέρος του προγράμματος που εκτελείται επαναληπτικά (καμία ή περισσότερες φορές).

Είσοδος  χρήστη

Πληροφορία που παρέχεται από εξωτερική πηγή την ώρα που εκτελείται το πρόγραμμα, μπορεί να αποθηκευτεί και να ανακληθεί όταν χρειάζεται.


1.5.4. Σχόλιο για την τάξη και τη λογική

Για να επιταχύνετε την διαδικασία ανάπτυξης, θα πρέπει να έχετε αποφασίσει εκ των προτέρων τη λογική του. Αυτό είναι το πρώτο σας βήμα όταν αναπτύσσειτε ένα σενάριο.

Μπορείτε να χρησιμοποιήσετε διάφορες μεθόδους: μια από τις ποιο συνηθισμένες είναι να δουλεύετε με λίστες. Αν δημιουργήσετε μια λίστα των εργασιών που εμπλέκονται σε ένα πρόγραμμα τότε μπορείτε να περιγράψετε καλύτερα κάθε διεργασία. Συγκεκριμένες εργασίεςστη λίστα μπορεί να αναφερθούν με τον αριθμό τους.

Η χρήση φυσικής γλώσσα για τη περιγραφή των εργασιών που θα εκτελεστούν από το πρόγραμμα θα σας βοηθήσει να δημιουργήσετε μια κατανοητή μορφή του προγράμματός σας. Αργότερα, μπορείτε να αντικαταστήσετε την πρόταση φυσικής γλώσσας με λέξεις και δομές γλώσσας φλοιού.

Το παρακάτω παράδειγμα δείχνει τέτοια λογική σχεδίαση. Περιγράφει την ανακύκλωση (rotation) αρχείων καταγραφής. Το παράδειγμα δείχνει μια πιθανή επαναληπτική δομή, ελεγχόμενη από τον αριθμό των αρχείων καταγραφής που θέλετε να ανακυκλώσετε:

1.      Θέλεις να  ανακυκλωσεις αρχεία καταγραφής;

a.       Αν ναι:

                                                         i.            Δώσε το όνομα διαδρομής το οποίο περιέχει τα αρχεία που θα ανακυκλωθούν.

                                                       ii.            Δώσε όνομα βάσης του αρχείου καταγραφής.

                                                      iii.            Δώσε τον αριθμό των ημερών που θα κρατηθούν τα αρχεία καταγραφής.

                                                     iv.            Κάνε μόνιμες ρυθμίσεις στο αρχείο crontab του χρήστη.

b.      Αν όχι, πήγαινε στο βήμα 3.

2.      Θέλεις να ανακυκλώσεις άλλο πακέτο αρχέιων καταγραφής;

a.       Αν ναι: επανέλαβε το βήμα 1.

b.      Αν όχι: πήγαινε στο βήμα 3.

3.      Έξοδος

Ο χρήστης θα παρέχει πληροφορίες ώστε το πρόγραμμα να κάνει κάτι. Η είσοδος από τον χρήστη πρέπει να ανακτηθεί και να αποθηκευτεί. Ο χρήστης πρέπει να ειδοποιηθεί ότι το crontab αρχείο του θα μεταβληθεί.


1.5.5. Ένα παράδειγμα σεναρίου Bash: mysystem.sh

Το σενάριο mysystem.sh εκτελεί κάποιες αρκετά γνωστές εντολές (date, w, unameuptime) για να παρουσιάσει πληροφορίες για το χρήστη και για τον υπολογιστή.

 
tom:~> cat -n mysystem.sh
     1  #!/bin/bash
     2  clear
     3  echo "This is information provided by mysystem.sh.  Program starts now."
     4
     5  echo "Hello, $USER"
     6  echo
     7
     8  echo "Today's date is `date`, this is week `date +"%V"`."
     9  echo
    10
    11  echo "These users are currently connected:"
    12  w | cut -d " " -f 1 - | grep -v USER | sort -u
    13  echo
    14
    15  echo "This is `uname -s` running on a `uname -m` processor."
    16  echo
    17
    18  echo "This is the uptime information:"
    19  uptime
    20  echo
    21
    22  echo "That's all folks!"

Ένα σενάριο πάντα ξεκινά με τους ίδιους δύο χαρακτήρες, "#!". Στην συνέχεια, στην ίδια γραμμή ορίζεται ο φλοιός που θα εκτελέσει τις εντολές που ακολουθούν. Αυτό το σενάριο ξεκινά καθαρίζοντας την οθόνη στην γραμμή 2. Η γραμμή 3 εμφανίζει ένα μήνυμα, πληροφορώντας τον χρήστη για το τι θα συμβεί. Η γραμμή 5 καλωσορίζει τον χρήστη. Οι γραμμές 6, 9, 13, 16 και 20 είναι εκεί μόνο για λόγους καλύτερης εμφάνισης των αποτελεσμάτων. Η γραμμή 8 εκτυπώνει την τρέχουσα ημερομηνία και τον αριθμό της εβδομάδας. Η γραμμή 11 είναι ξανά ένα μήνυμα πληροφόρησης, όπως οι γραμμές 3, 18 και 22. Η γραμμή 12 μορφοποιεί την έξοδο της w; η γραμμή 15 εμφανίζει το λειτουργικό σύστημα και πληροφορίες για τον επεξεργαστή. Η γραμμή 19 δίνει τις πληροφορίες της εντολής uptime.

Τόσο οι echo όσο και η printf είναι εσωτερικές εντολές του Bash. Η πρώτη πάντα τερματίζεται με κατάσταση 0, και απλά εκτυπώνει ορίσματα ακολουθούμενα από ένα χαρακτήρα τέλους γραμμής στην πρότυπη έξοδο, ενώ η δεύτερη επιτρέπει τον ορισμό ενός αλφαριθμητικού μορφοποίησης και επιστρέφει κώδικα μη μηδενικής εξόδου στην αποτυχία.

Αυτό είναι το ίδιο σενάριο με χρήση της εντολής printf:

 
tom:~> cat mysystem.sh
#!/bin/bash
clear
printf "This is information provided by mysystem.sh.  Program starts now."
 
printf "Hello, $USER.\n\n"
 
printf "Today's date is `date`, this is week `date +"%V"`.\n\n"
 
printf "These users are currently connected:\n"
w | cut -d " " -f 1 - | grep -v USER | sort -u
printf "\n"
 
printf "This is `uname -s` running on a `uname -m` processor.\n\n"
 
printf "This is the uptime information:\n"
uptime
printf "\n"
 
printf "That's all folks!\n"

Η δημιουργία σεναρίων φιλικών προς τον χρήστη μέσω ενδιαφερόντων μηνυμάτων παρουσιάζεται στο Κεφάλαιο 8.

Note

Τυπική τοποθεσία του Bourne Again φλοιού

 

Υποθέτουμε ότι το πρόγραμμα bash είναι εγκατεστημένο στο /bin.

Warning

Αν η πρότυπη έξοδος (stdout) δεν είναι διαθέσιμη

 

Αν εκτελείτε ένα σενάριο από το cron, θα πρέπει να δίνετε πλήρη ονόματα διαδρομών και να ανακατευθύνετε τη πρότυπη έξοδο και το πρότυπο σφάλμα (stdout και stderr). Αν δεν το έχουμε σκεφτεί, οποιαδήποτε λάθη αναγκάζουν το σενάριο να τερματίσει πρόωρα, αφού ο φλοιός εκτελείται σε μη-διαλογική κατάσταση, .

Το κεφάλαιο που ακολουθεί θα παρουσιάσει λεπτομερώς τα παραπάνω σενάρια.


1.5.6. Παράδειγμα σεναρίου εκκίνησης (init)

Ένα σενάριο εκκίνησης σε συστήματα UNIX και Linux ξεκινά τις υπηρεσίες του συστήματος. Ο δαίμονας καταγραφής συστήματος, ο δαίμονας διαχείρισης ισχύος, οι δαίμονες ονομασίας και αλληλογραφίας είναι συνηθισμένα παραδείγματα. Αυτά τα σενάρια, επίσης γνωστά και ως σενάρια αρχικοποίησης, είναι αποθηκευμένα σε μια συγκεκριμένη τοποθεσία στο σύστημά σας, όπως /etc/rc.d/init.d ή /etc/init.d. Η init, αρχική διεργασία, διαβάζει τα αρχεία ρυθμίσεών της της και αποφασίζει ποιες υπηρεσίες να εκκινήσει ή να τερματίσει σε κάθε επίπεδο εκτέλεσης (runlevel). Το επίπεδο εκτέλεσης είναι μια συνολική ρύθμιση των διεργασιών που εκκινούν μαζί με το σύστημα. Κάθε σύστημα έχει ένα επίπεδο εκτέλεσης απλού χρήστη, για παράδειγμα, για να φέρει εις πέρας εργασίες διαχείρισης, για τις οποίες το σύστημα πρέπει να είναι σε μια όσο το δυνατόν αδρανή κατάσταση, όπως λόγου χάρη κατά την επανάκτηση ενός κρίσιμου αρχείου συστήματος από εφεδρικά αντίγραφα. Συνήθως τα επίπεδα εκτέλεσης της επανεκκίνησης και του τερματισμού είναι επίσης προ-ρυθμισμένα.

Οι εργασίες που πρέπει να εκτελεστούν κατά την εκκίνηση ή τερματισμό μιας υπηρεσίας καταγράφονται στο αντίστοιχο σενάριο εκκίνσης. Μια από τις βασικές εργασίες διαχείρισης συστήματος είναι η διαμόρφωση της init, έτσι ώστε ο σωστές υπηεσίες να εκκινούν ή να τερματίζονται στο σωστό χρόνο. Η δουλειά αυτή απαιτεί κατανόηση των διαδικασιών εκκίνησης και τερματισμού του συστήματος. Σας συμβουλεύουμε να διαβάσετε τις σελίδες του εγχειριδίου για την init και το inittab πριν ασχοληθείτε με τα σενάρια εκκίνησης.

Εδώ είναι ένα πολύ απλό παράδειγμα, που παράγειι έναν ήχο κατά την εκκίνηση και τον τερματισμό του υπολογιστή:

 
#!/bin/bash
 
# This script is for /etc/rc.d/init.d
# Link in rc3.d/S99audio-greeting and rc0.d/K01audio-greeting
 
case "$1" in
'start')
  cat /usr/share/audio/at_your_service.au > /dev/audio
  ;;
'stop')
  cat /usr/share/audio/oh_no_not_again.au > /dev/audio
  ;;
esac
exit 0

Η εντολή case χρησιμοποιείταισυχνά σε τέτοιου είδους σενάρια και περιγράφεται στην Ενότητα 7.2.5.


1.6. Περίληψη

Το Bash είναι ο GNU φλοιός, συμβατός με τον Bourne φλοιό και ενσωματώνει πολλά χρήσιμα χαρακτηριστικά άλλων φλοιών. Όταν ο φλοιός ξεκινάει, διαβάζει τα αρχεία ρύθμισής του. Τα ποιο σημαντικά είναι:

·         /etc/profile

·         ~/.bash_profile

·         ~/.bashrc

Το Bash συμπεριφέρεται διαφορετικά όταν διαλόγική ή μη-διαλογική κατάσταση και επίσης παρέχει μια περιορισμένη κατάσταση POSIX - συμβατότητας.

Οι εντολές φλοιού μπορούν να χωριστούν σε τρεις ομάδες: τις συναρτήσεις φλοιού, εσωτερικές εντολές φλοιού και τις εντολές που βρίσκονται σε ένα κατάλογο στο σύστημα. Το Bash υποστηρίζει επιπρόσθετες εσωτερικές εντολές που δεν υπάρχουν στον απλό Bourne φλοιό.

Τα σενάρια φλοιού αποτελούνται από τέτοιες εντολές οργανωμένες με βάση το συντακτικό του φλοιού. Τα σενάριαδιαβάζονται και εκτελούνται ακολουθιακά και πρέπει να έχουν μια λογική δομή.


1.7. Ασκήσεις

Μερικές ασκήσεις που θα σας προετοιμάσουν για το επόμενο κεφάλαιο:

1.      Σε ποιο σημείο του συστήματός σου βρίσκεται το πρόγραμμα bash;

2.      Χρησιμοποιήστε την επιλογή --version για να μάθετε ποια έκδοση έχετε.

3.      Ποια αρχεία ρύθμισης φλοιού διαβάζονται όταν συνδέεστε στο σύστημά σας χρησιμοποιώντας την γραφική διεπαφή χρήστη και μετά ανοίγετε ένα παράθυρο τερματικού;

4.      Είναι οι ακόλουθοι φλοιοί διαλογικοί; Είναι φλοιοί σύνδεσης;

o        Ένας φλοιός που ανοίγει κάνοντας κλικ στο υπόβαθρο της γραφικής σου επιφάνειας εργασίας ή επιλέγοντας "Τερματικόl" ή κάτι τέτοιο από ένα μενού.

o        Ένας φλοιός που λαμβάνετε μόλις εισάγετε την εντολή ssh localhost.

o        Ένας φλοιός που λαμβάνετε όταν συνδέεστε στο σύστημα σε κατάσταση κειμένου.

o        Ένας φλοιός που αποκτάται με την εντολή xterm &.

o        Ένας φλοιός που ανοίγει με το σενάριο mysystem.sh.

o        Ένας φλοιός που λαμβάνετε από απομακρυσμένη είσοδο, για την οποία δεν χρειάστηκε να δώσετε το όνομα  χρήστη και/ ή τον κωδικό πρόσβασης επειδή χρησιμοποιείτε SSH και ίσως SSH κλειδιά.

5.      Μπορείτε να εξηγήσετε γιατί το bash δεν τερματίζεται όταν πληκτρολογείτε Ctrl+C στην γραμμή εντολών;

6.      Εμφάνισε το περιεχόμενο της στοίβας καταλόγων.

7.      Αν δεν είναι ήδη έτσι ρυθμισμένη, ρυθμίστε την προτροπής σας ώστε να εμφανίζει τον τρέχοντα κατάλογό σας, για παράδειγμα πρόσθεσε αυτή τη γραμμή στο ~/.bashrc:

export PS1="\u@\h \w> "

8.      Εμφάνισε hashed εντολές για την τρέχουσα σύνοδο του φλοιού σας.

9.      Πόσες διεργασίες εκτελούνται στο σύστημά σας; Χρησιμοποίησε τις ps και wc, η πρώτη γραμμή εξόδου της ps δεν είναι διεργασία!

10.  Πώς θα εμφανίσετε το όνομα του συστήματος; Μόνο το όνομα, τίποτα άλλο!


Κεφάλαιο 2. Συγγραφή και εκσφαλμάτωση σεναρίων

Μόλις τελειώσετε αυτό το κεφάλαιο θα μπορείτε:

·         Να γράψετε ένα απλό σενάριο.

·         Να ορίσετε τον τύπο του φλοιού που πρέπει να εκτελέσει το σενάριο

·         Να τοποθετήσετε σχόλια στον κώδικα των σεναρίου σας.

·         Να αλλάξετε τις άδειες προσπέλασης ενός σεναρίου.

·         Να εκτελέσετε και να εκσφαλματώσετε ένα σενάριο.


2.1. Δημιουργία και εκτέλεση ενός σεναρίου

2.1.1. Συγγραφή και ονομασία

Ένα σενάριο φλοιού είναι μια ακολουθία εντολών τις οποίες χρησιμοποιείτε κατ' επανάληψη. Αυτή η ακολουθία τυπικά εκτελείται εισάγοντας το όνομα του σεναρίου στην γραμμή εντολών. Εναλλακτικά, μπορείτε να χρησιμοποιείτε σενάρια για να αυτοματοποιήσετε διαδικασίες χρησιμοποιώντας την υπηρεσία cron. Μια άλλη χρήση σεναρίων είναι η διαδικασία εκκίνησης και τερματισμού του UNIX, όπου οι  λειτουργίες των δαιμόνων και  των υπηρεσιών ορίζονται με τα σενάρια εκκίνσης.

Για να δημιουργήσετε ένασενάριο φλοιού, ανοίξτε ένα καινούργιο άδειο αρχείο σε ένα συντάκτη κειμένου. Οποιοσδήποτε συντάκτης αρκεί:  vim, emacs, gedit, dtpad κλπ είναι όλοι έγκυροι. Ίσως όμως θελήσετε να χρησιμοποιήσετε ένα πιο προχωρημένο συντάκτη όπως ο vim ή ο emacs, γιατί αυτοί μπορούν να ρυθμιστούν να αναγνωρίζουν τη σύνταξη του φλοιού Bash και μπορούν να αποτελέσουν πολύτιμη βοήθεια αποτρέποντας λάθη που οι αρχάριοι κάνουν συχνά, όπως να παράλειψη παρενθέσεων και τερματικών συμβόλων.

Τοποθετήστε εντολές UNIX σε ένα καινούργιο άδειο αρχείο, σαν να τις γράφατε στην γραμμή εντολών. Όπως συζητήθηκε στο προηγούμενο κεφάλαιο, (δείτε Ενότητα 1.3), οι εντολές μπορεί να είναι συναρτήσεις φλοιού, εσωτερικές εντολές φλοιού, εντολές του UNIX και άλλα σενάρια.

Δώστε στο σενάριό σας ένα λογικό όνομα που να δίνει μια ιδέα σχετικά με το τι κάνει. Σιγουρευτείτε ότι το όνομα του σεναρίου σας δεν είναι ίδιο με κάποιο από τα υπάρχοντα αρχεία. Για να σιγουρευτείτε ότι δεν μπορεί να υπάρξει σύγχυση, τα ονόματα των σεναρίων συχνά τελειώνουν σε .sh. Ακόμη και έτσι, μπορούν να υπάρχουν και άλλα σενάρια στο σύστημα σας με το ίδιο όνομα που διαλέξατε. Σιγουρευτείτε κάνοντας χρήση των εντολών which, whereis και άλλων εντολές για την αναζήτηση προγραμμάτων και αρχείων: 

which -a script_name

whereis script_name

locate script_name


2.1.2. script1.sh

Σε αυτό το παράδειγμα χρησιμοποιούμε την εσωτερική εντολή echo για να ενημερώσουμε τον χρήστη για το τι πρόκειται να συμβεί, πρίν εκτελεστεί η εντολή που θα δημιουργήσει το αποτέλεσμα  Καλό είναι να ενημερώνετε τους χρήστες σχετικά με την λειτουργία των εντολών, για να τους αποτρέψετε να γίνουν νευρικοί πιστεύοντας ότι το σενάριο δεν κάνει τίποτα. Θα επιστρέψουμε στο θέμα αυτό (ενημέρωση χρηστών) στο Κεφάλαιο 8.

Εικόνα 2-1. script1.sh

Εικόνα 2-1

Γράψτε αυτό το σενάριο μόνοι σας. Είναι καλή ιδέα να δημιουργήσετε ένα κατάλογο ~/scripts όπου να αποθηκεύετε τα σενάριά σας. Προσθέστε αυτόν το κατάλογο στη μεταβλητή PATH :

export PATH="$PATH:~/scripts"

Αν είστε καινούργιοι στο Bash, χρησιμοποιήστε έναν συντάκτη κειμένου που χρησιμοποιεί διαφορετικά χρώματα για τις διαφορετικές δομές. Χρωματική υποβοήθη υποστηρίζουν οι vim, gvim, (x)emacs, kwrite, gedit και πολλοί άλλοι συντάκτες, ελέγξτε τη σχετική τεκμηρίωση.

Note

Διαφορετικές προτροπές

Οι προτροπές στο εγχειρίδιο μπορεί να αλλάζουν ανάλογα με την διάθεση του συγγραφέα. Αυτό αντιπροσωπεύει πιο πολύ πραγματικές καταστάσεις απο το εκπαιδευτικό σύμβολο προτροπής $. Η μόνη σύμβαση που χρησιμοποιούμε είναι ότι η προτροπή root τελειώνει με ένα hash (#).


2.1.3. Εκτέλεση του σεναρίου

Το σενάριο για να μπορεί να εκτελεστεί πρέπει να παρέχει δικαιώματα εκτέλεσης στους σωστούς χρήστες. Όταν ορίζετε τα δικαιώματα, σιγουρευτείτε ότι πραγματικά αποκτήσατε τα δικαιώματα που επιθυμούσατε. Όταν αυτό ολοκληρωθεί, το σενάριο μπορεί να εκτελεστεί όπως μια κοινή εντολή:

 
willy:~/scripts> chmod u+x script1.sh
 
willy:~/scripts> ls -l script1.sh
-rwxrw-r--    1 willy  willy          456 Dec 24 17:11 script1.sh
 
willy:~> script1.sh
The script starts now.
Hi, willy!
 
I will now fetch you a list of connected users:
 
3:38pm  up 18 days,  5:37,  4 users,  load average: 0.12, 0.22, 0.15
USER  	TTY      FROM         LOGIN@   IDLE   JCPU   PCPU  WHAT
root 	tty2 	 -             Sat 2pm  4:25m  0.24s  0.05s  -bash
willy   :0	 -             Sat 2pm   ?     0.00s   ?     -
willy   pts/3    -             Sat 2pm  3:33m 36.39s 36.39s  BitchX willy ir
willy   ts/2     -             Sat 2pm  3:33m  0.13s  0.06s  /usr/bin/screen
 
I'm setting two variables now.
This is a string: black
And this is a number: 9
 
I'm giving you back your prompt now.
 
willy:~/scripts> echo $COLOUR
 
willy:~/scripts> echo $VALUE
 
willy:~/scripts>

Αυτός είναι ο πιο συνηθισμένος τρόπος εκτέλεσης ενός σεναρίου. Ένα τέτοιο σενάριο είναι προτιμότερο να εκτελεστεί σε ένα υποφλοιό. Οι μεταβλητές, οι λειτουργίες, και τα ψευδώνυμα που δημιουργούνται σε αυτόν τον υποφλοιό είναι γνωστά μόνο στην συγκεκριμένη χρήση του υποφλοιού. 'Οταν αυτός ο φλοιός τερματιστεί και ο γονικός φλοιός επανέλθει στο προσκήνιο, τα πάντα καθαρίζονται και όλες οι αλλαγές στην κατάσταση του φλοιού που έγιναν απο το σενάριο, διαγράφονται.

Αν δεν έχετε βάλει τον κατάλογο scripts στο PATH, και το . (ο τρέχων κατάλογος) δεν βρίσκεται και αυτός στο PATH, ενεργοποιείτε στο σενάριο ως εξής:

./script_name.sh

Επίσης, ένα σενάριο μπορεί να εκτελεστεί ρητά με ένα δεδομένο φλοιό, αλλά γενικά αυτό το κάνουμε αν θέλουμε να πετύχουμε κάτι συγκεκριμένο,  όπως να σιγουρευτούμε αν το σενάριο δουλεύει με ένα άλλο φλοιό ή να εμφανίσουμε ίχνη για εκσφαλμάτωση:

rbash script_name.sh

sh script_name.sh

bash -x script_name.sh

Ο επιλεγμένος φλοιός θα ξεκινήσει σαν ένας υποφλοιόςς του τρέχοντος λοιού και θα εκτελέσει το σενάριο. Αυτό γίνεται όταν θέλετε το σενάριο να ξεκινήσει με συγκεκριμένες επιλογές ή κάτω από συγκεκριμένες καταστάσεις που δεν προσδιορίζονται στοσενάριο.

Εάν δεν θέλετε να ξεκινήσει ένας καινούργιος φλοιός αλλά να εκτελέσετε το σενάριο στον τρέχοντα φλοιό, χρησιμοποιείστε την εντολή source:

source script_name.sh

Tip

source = .

Η ενσωματωμένη εντολή source του Bash είναι συνώνυμι της εντολής  . (dot).

Σε αυτή την περίπτωση το σενάριο δεν χρειάζεται άδεια εκτέλεσης. Οι εντολές εκτελούνται στον τρέχντα φλοιό, και για αυτό το λόγο οι αλλαγές που θα γίνουν στο περιβάλλον σας θα είναι ορατές όταν το σενάριο τερματιστεί:

 
willy:~/scripts> source script1.sh
--output ommitted--
 
willy:~/scripts> echo $VALUE
9
 
willy:~/scripts>

2.2. Τα βασικά των σεναρίων

2.2.1. Ποιός φλοιός θα εκτελέσει το σενάριο;

Όταν εκτελείιτε ένα σενάριο σε ένα υποφλοιό, πρέπει να ορίσετε με ποιό φλοιό θα εκελεστεί. Ο τύπος του φλοιού στον οποίο γράψατε το σενάριο μπορεί να μην είναι ο προεπιλεγμένος στο σύστημα σας, και έτσι οι εντολές που εισάγατε μπορεί να οδηγήσουν σε λάθη όταν εκτελούνται από λάθος φλοιό.

Η πρώτη γραμμή του σεναρίου αποφασίζει ποιος φλοιός θα ξεκινήσει.Οι πρώτοι δυο χαρακτήρες της πρώτης γραμμής πρέπει να είναι #!, και μετά ακολουθεί η διαδρομή προς το φλοιό που μπορεί και διερμηνεύσει τις εντολές που ακολουθούν. Οι κενές γραμμές θεωρούνται κανονικές γραμμές, για αυτό το λόγο μην ξεκινήσετε το σενάριό σας με μια κενή γραμμή.

Για τον σκοπό αυτού του εγχειριδίου, όλα τα σενάριά σας θα ξεκινούν με την γραμμή:

#!/bin/bash

Όπως σημειώθηκε προηγούμενα, αυτό υπονοεί ότι το εκτελέσιμο του Bash βρίσκεται στο /bin.


2.2.2. Προσθήκη σχολίων

Πρέπει να καταλάβετε ότι πολλές φορές δεν θα είστε οι μοναδικοί που διαβάζετε τον κώδικά σας. Πολλοί χρήστες και διαχειριστές συστημάτων εκτελούν σενάρια που είναι γραμμένα από άλλους. Αν κάποιος θελήσει να μελετήσει  ένα σενάριο, τα σχόλια είναι χρήσιμα για να κατατοπίσουν τον αναγνώστη.

Επίσης, τα σχόλια κάνουν την ζωή σας πιο εύκολη. Ας πούμε ότι χρειάστηκε να διαβάσετε πολλές σελίδες για να πετύχετε ένα συγκεκριμένο αποτέλεσμα με κάποια εντολή που χρησιμοποιήσατε στο σενάριό σας. Αν χρειαζόταν να αλλάξετε το σενάριό σας μετά από  μερικές εβδομάδες ή μήνες, και δεν έχετε σχολιάσει τον κώδικα σας σχετικά με το τι κάνατε, πώς το κάνατε, και γιατί το κάνατε, πιθανότατα δεν θα θυμάστε πως τα καταφέρατε. 

Πάρτε το παράδειγμα του script1.sh και αντιγράψτε το σε commented-script1.sh, το οποίο θα αλλάξουμε έτσι ώστε τα σχόλια να αντικατοπτρίζουν την λειτουργία του. Οτιδήποτε βρίσκεται μετά το hash αγνοείται μετά το άνοιγμα του αρχείου:

 
#!/bin/bash
# This script clears the terminal, displays a greeting and gives information
# about currently connected users.  The two example variables are set and displayed.
 
clear                          # clear terminal window
 
echo "The script starts now."
 
echo "Hi, $USER!"              # dollar sign is used to get content of variable
echo
 
echo "I will now fetch you a list of connected users:"
echo                                                 
w                              # show who is logged on and
echo                           # what they are doing
 
echo "I'm setting two variables now."
COLOUR="black"                                # set a local shell variable
VALUE="9"                                     # set a local shell variable
echo "This is a string: $COLOUR"              # display content of variable 
echo "And this is a number: $VALUE"           # display content of variable
echo
 
echo "I'm giving you back your prompt now."
echo

Σε ένα αξιοπρεπές σενάριο, οι πρώτες γραμμές είναι συνήθως σχόλια σχετικά με το τι να περιμένουμε. Επίσης κάθε ομάδα εντολών πρέπει να σχολιαστεί για λόγους κατανόησης του σεναρίου. Τα σενάρια εκκίνησης του Linux, για παράδειγμα, στον κατάλογο init.d , συχνά σχολιάζονται συστηματικά αφού πρέπει να είναι κατανοητά και τροποποιήσιμα από οποιονδήποτε εκτελεί Linux.


2.3. Εκσφαλμάτωση σεναρίων Bash 

2.3.1. Εκσφαλμάτωση ολόκληρου σεναρίου

Όταν τα πράγματα δεν πηγαίνουν όπως περιμένουμε, πρέπει είμαστε σε θέση να καταλάβουμε τι ακριβώς δεν πήγε καλά. Το Bash παρέχει πολλά χαρακτηριστικά  που βοηθούν στην εκσφαλμάτωση. Το πιο συνηθισμένο είναι να ξεκινήσουμε τον υποφλοιό με την επιλογή -x, η οποία θα εκτελέσει ολόκληρο το σενάριο σε κατάσταση εκσφαλμάτωσης. Τα ίχνη της κάθε εντολής μαζί με τα ορίσματα της εμφανίζονται στην πρότυπη έξοδο (stdout) αφότου οι εντολές έχουν επεκταθεί αλλά πριν εκτελεστούν.

Αυτό είναι το σενάριο commented-script1.sh  που εκτελέιται σε κατάσταση εκσφαλμάτωσης. Σημειώστε ξανά ότι τα σχόλια δεν είναι ορατά στα αποτελέσματα του σεναρίου.

 
willy:~/scripts> bash -x script1.sh
+ clear
 
+ echo 'The script starts now.'
The script starts now.
+ echo 'Hi, willy!'
Hi, willy!
+ echo
 
+ echo 'I will now fetch you a list of connected users:'
I will now fetch you a list of connected users:
+ echo
 
+ w
  4:50pm  up 18 days,  6:49,  4 users,  load average: 0.58, 0.62, 0.40
USER     TTY      FROM           LOGIN@   IDLE   JCPU   PCPU  WHAT
root     tty2     -              Sat 2pm  5:36m  0.24s  0.05s  -bash
willy    :0       -              Sat 2pm   ?     0.00s   ?     -
willy    pts/3    -              Sat 2pm 43:13  36.82s 36.82s  BitchX willy ir
willy    pts/2    -              Sat 2pm 43:13   0.13s  0.06s  /usr/bin/screen
+ echo
 
+ echo 'I'\''m setting two variables now.'
I'm setting two variables now.
+ COLOUR=black
+ VALUE=9
+ echo 'This is a string: '
This is a string:
+ echo 'And this is a number: '
And this is a number:
+ echo
 
+ echo 'I'\''m giving you back your prompt now.'
I'm giving you back your prompt now.
+ echo

 

Note

Νέα χαρακτηριστικά Bash 

Από την έκδοση bash-3.0 και μεταγενέστερα το Bash περιλαμβάνει ένα ενισχυμένο σύστημα εκσφαλμάτωσης. Για παλιότερες εκδόσεις, ανώτερες του bash-2.05, διατίθεται αντίστοιχο patch στο SourceForge


2.3.2. Εκσφαλμάτωση τμημάτων του σεναρίου

Με την εντολή setτου Bash, μπορείτε να εκτελέσετε σε κανονική κατάσταση εκείνα τα τμήματα του σεναρίου, για τα οποία είστε σίγουρος ότι λειτουργούν χωρίς πρόβλημα, και να εμφαμίσετε πληροφορίες εκσφαλμάτωσης μόνο για τα προβληματικά τμήματα. Έστω ότι δεν είμαστε σίγουροι για το τι θα κάνει η εντολή w στο παράδειγμα commented-script1.sh, τότε μπορούμε να  προσθέσουμε στπ σενάριο κάτι σαν και αυτό:

 
set -x                  # activate debugging from here
w
set +x                 # stop debugging from here

Η έξοδος θα είναι κάπως έτσι:

 
willy: ~/scripts> script1.sh
The script starts now.
Hi, willy!
 
I will now fetch you a list of connected users:
 
+ w
  5:00pm  up 18 days,  7:00,  4 users,  load average: 0.79, 0.39, 0.33
USER     TTY      FROM          LOGIN@   IDLE   JCPU   PCPU  WHAT
root     tty2     -             Sat 2pm  5:47m  0.24s  0.05s  -bash
willy    :0       -             Sat 2pm   ?     0.00s   ?     -
willy    pts/3    -             Sat 2pm 54:02  36.88s 36.88s  BitchX willyke
willy    pts/2    -             Sat 2pm 54:02   0.13s  0.06s  /usr/bin/screen
+ set +x
 
I'm setting two variables now.
This is a string:
And this is a number:
 
I'm giving you back your prompt now.
 
willy: ~/scripts>

Μπορείτε να ενεργοποιήσετε και να απενεργοποιήσετε την κατάσταση εκσφαλμάτωσης όσες φορές θέλετε μέσα στο ίδιο σενάριο.

Ο παρακάτω πίνακας δίνει μία σύνοψη άλλων χρήσιμων εντολών εκσφαλμάτωσης για το Bash:

Πίνακας 2-1. Επισκόπηση των επιλογών εκσφαλμάτωσης της εντολής set 

Σύντομη γραφή

Ανεπτυγμένη γραφή

Αποτέλεσμα

set -f

set -o noglob

Απενεργοποιεί τη δημιουργία ονομάτων αρχείων με χρήση μεταχαρακτήρων (globbing).

set -v

set -o verbose

Εμφανίζει τις γραμμές εισόδου του φλοιού μόλις διαβάζονται.

set -x

set -o xtrace

Εμφανίζει τα ίχνη των εντολών πριν εκτελεστούν.

Η παύλα σημαίνει ενεργοποίηση της επιλογής και το συν σημαίνει απενεργοποίηση. Προσοχή μην μπερδευτείτε!

Στο παρακάτω παράδειγμα, επιδεικνύουμε τις επιλογές στη γραμμή εντολών:

 
willy:~/scripts> set -v
 
willy:~/scripts> ls
ls 
commented-scripts.sh   script1.sh
 
willy:~/scripts> set +v
set +v
 
willy:~/scripts> ls *
commented-scripts.sh    script1.sh
 
willy:~/scripts> set -f
 
willy:~/scripts> ls *
ls: *: No such file or directory
 
willy:~/scripts> touch *
 
willy:~/scripts> ls
*   commented-scripts.sh    script1.sh
 
willy:~/scripts> rm *
 
willy:~/scripts> ls
commented-scripts.sh    script1.sh

Εναλλακτικά, αυτές οι καταστάσεις μπορούν να προσδιοριστούν μέσα στο ίδιο το σενάριο, τοποθετώντας τις επιλογές που θέλετε στην πρώτη γραμμή δήλωσης του φλοιού. Οι επιλογές μπορούν να συνδιαστούν, όπως συμβαίνει συνήθως με τις εντολές UNIX:

#!/bin/bash -xv

Μόλις βρείτε το προβληματικό τμήμα του σεναρίου, μπορείτε να τοποθετήσετε εντολές echo πριν από κάθε εντολή για την οποία δεν είστε βέβαιοι, και έτσι θα μπορέσετε να βρείτε ακριβώς σε ποιό σημείο τα πράγματα δεν δούλεψαν. Στο παράδειγμα του σεναρίου commented-script1.sh, υποθέτοντας ότι η εμφάνιση των χρηστών δημιουργεί πρόβλημα, μπορούμε να έχουμε:

echo "debug message: now attempting to start w command"; w

Σε πιο προχωρημένα σενάρια, η εντολή echo μπορεί να χρησιμοποιηθεί για την εμφάνιση του περιεχομένου (της τιμής) μεταβλητών σε διάφορα στάδια εκτέλεσης του σεναρίου και τον εντοπισμό λαθών:

 
echo "Variable VARNAME is now set to $VARNAME."

2.4. Περίληψη

Ένα σενάριο φλοιού είναι μία επαναχρησιμοποιήσιμη σειρά εντολών οποθετημένων σε ένα εκτελέσιμο αρχείο κειμένου. Οποιοσδήποτε συντάκτης κειμένου μπορεί να χρησιμοποιηθεί για τη συγγραφή σεναρίων.

Τα σενάρια αρχίζουν με #! και ακολουθεί η διαδρομή προς τον φλοιό που εκτελεί τις εντολές από το σεναρίου. Τα σχόλια προστίθενται σε ένα σενάριο για την δική σας μελλοντική αναφορά, όπως επίσης και για να είναι κατανοητός ο κώδικάς σας από άλλους. Είναι καλύτερο να συμπεριλάβετε πολλές εξηγήσεις από το να μην συμπεριλάβετε καθόλου.

Η εκσφαλμάτωση ενός σεναρίου μπορεί να γίνει με την χρήση επιλογών του φλοιού. Οι επιλογές του φλοιού μπορούν να χρησιμοποιηθούν για μερική αποσφαλμάτωση ή για την ανάλυση ολόκληρου του σεναρίουt. Η εισαγωγή των εντολών echo σε στρατηγικά σημεία στον κώδικά σας είναι μια  συνιθισμένη τεχνική που λύνει πολλά προβλήματα.


2.5. Ασκήσεις

Αυτές οι ασκήσεις θα σας βοηθήσουν να δημιουργήσετε το πρώτο σας σενάριο.

1.      Γράψτε άνα σενάριο με τη βοήθεια του συντάκτη κειμένου που προτιμάτε. Το σενάριο πρέπει να εμφανίζει τη διαδρομή για τον οικείο σας κατάλογο και τον τύπο τερματικού που χρησιμοποιείτε. Επίσης εμφανίζει όλες τις υπηρεσίες που ξεκινούν στο επίπεδο εκτέλεσης 3 του συστήματός σας (υπόδειξη: χρησιμοποιείστε τα HOME, TERM and ls /etc/rc3.d/S*)

2.      Προσθέστε σχόλια στο σενάριό σας.

3.      Προσθέστε πληροφορίες για τους χρήστες του σεναρίου σας.

4.      Αλλάξτε τις άδειες προσπέλασης του σεναρίου για να μπορέσετε να το εκτελέσετε.

5.      Εκτελέστε το σενάριο σε κανονική κατάσταση και σε κατάσταση εκσφαλμάτωσης. Πρέπει να εκτελείται χωρίς σφάλματα.

6.      Κάντε μερικά λάθη στο σενάριό σας: Δείτε τι συμβαίνει αν γράψετε λάθος μερικές εντολές, αν παραλείψετε την πρώτη γραμμή ή τοποθετήστε κάτι μη αναγνώσιμο εκεί, ή αν γράψετε λανθασμένα ονόματα μεταβλητών του κελύφους ή αν γράψετε λάθος ονόματα μεταβλητών του κελύφους π.χ. με μικρά γράμματα ενώ έχουν δηλωθεί με κεφαλαία. Ελέγξτε τα σχόλια της εκσφαλμάτωσης σχετικά με αυτά τα λάθη.


Κεφάλαιο 3. Το περιβάλλον Bash

Σε αυτό το κεφάλαιο θα συζητήσουμε διάφορους τρόπους με τους οποίους επηρεάζεται το περιβάλλον Bash :

·         Τροποποίηση των αρχείων ρύθμισης

·         Χρήση μεταβλητών

·         Χρήση διαφόρων τύπων εισαγωγικών

·         Εκτέλεση αριθμητικών υπολογισμών

·         Ορισμός ψευδωνύμων

·         Χρήση επέκτασης και αντικατάστασης


3.1. Αρχεία ρύθμισης φλοιού

3.1.1. Αρχεία ρύθμισης για όλο το σύστημα

3.1.1.1. /etc/profile

Όταν το Bash καλείται διαλογικά με την επιλογή  --login ή  όταν καλέιται με την εντολή sh, τότε διαβάζει τις ρυθμίσεις στο αρχείο /etc/profile. Αυτές συνήθως  θέτουν τις μεταβλητές φλοιού PATH, USER, MAIL, HOSTNAME and HISTSIZE.

Σε μερικά συστήματα, η τιμή umask ρυθμίζεται στο /etc/profile. Σε άλλα συστήματα αυτό το αρχείο διατηρεί δείκτες σε άλλα αρχεία διαμόρφωσης όπως τα:

·         /etc/inputrc, ένα αρχείο ρύθμισης της Readline για όλο το σύστημα όπου μπορείτε να διαμορφώσετε το στυλ της γραμμής εντολών.

·         /etc/profile.d ένας κατάλογος, που περιέχει αρχεία ρύθμισης για όλο το σύστημα σχετικά με τη συμπεριφορά των ειδικών προγραμμάτων.

Όλες οι ρυθμίσεις που θέλετε να εφαρμόσετε σε όλα τα περιβάλλοντα των χρηστών σας πρέπει να είναι σε αυτό το αρχείο. Μπορεί να μοιάζει με αυτό:

# /etc/profile
 
# System wide environment and startup programs, for login setup
 
PATH=$PATH:/usr/X11R6/bin
 
# No core files by default
ulimit -S -c 0 > /dev/null 2>&1
 
USER="`id -un`"
LOGNAME=$USER
MAIL="/var/spool/mail/$USER"
 
HOSTNAME=`/bin/hostname`
HISTSIZE=1000
 
# Keyboard, bell, display style: the readline config file:
if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ]; then
    INPUTRC=/etc/inputrc
fi
 
PS1="\u@\h \W"
 
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE INPUTRC PS1
 
# Source initialization files for specific programs (ls, vim, less, ...)
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        . $i
    fi
done
 
# Settings for program initialization
source /etc/java.conf
export NPX_PLUGIN_PATH="$JRE_HOME/plugin/ns4plugin/:/usr/lib/netscape/plugins"
 
PAGER="/usr/bin/less"
 
unset i

Αυτό το αρχείο διαμόρφωσης θέτει μερικές βασικές μεταβλητές περιβάλλοντος φλοιού καθώς επίσης και μερικές μεταβλητές απαιτούμενες για χρήστες που εκτελούν την Java ή/και τις εφαρμογές της Java στον περιηγητή Ιστού τους. Δείτε την Ενότητα 3.2.

Δείτε το Κεφάλαιο 7 για περισσότερα στχοιχεία σχετικά με την χρήση του if σε αυτό το αρχείο. Το Κεφάλαιο 9 συζητά τους βρόχους όπως αυτός στη δομή for

Ο πηγαίος κώδικας του Bash περιέχει δείγματα από αρχεία profile για γενική και ατομική χρήση. Τόσο αυτά όσο και το παραπάνω παράδειγμα χρειάζονται τροποποιήσιεις για να δουλέψουν στο περιβάλλον σας!


3.1.1.2. /etc/bashrc

Τα συστήματα προσφέρουν πολλαπλούς τύπους φλοιών, θα ήταν καλό να βάλουμε ειδικές ρυθμίσεις του Bash σε αυτό το αρχείο, αφού το /etc/profile διαβάζεται και από άλλους φλοιούς, όπως ο φλοιός Bourne. Με τον διαχωρισμό τον αρχείων ρύθμισης για διαφορετικούς τύπους φλοιών αποφεύγουμε τα λάθη που προκαλούνται από τους φλοιούς που δεν αντιλαμβάνονται  το συντακτικό του φλοιού Bash. Σε τέτοιες περιπτώσεις, το αρχείο ~/.bashrc του χρήστη μπορεί να οδηγεί στο αρχείο /etc/bashrc για να το συμπεριλάβει στην διαδικασία αρχικοποίησης του φλοιού κατά τη σύνδεση.

Επίσης μπορεί να βρείτε ότι το /etc/profile στο σύστημά σας διατηρεί μόνο αρχικές ρυθμίσεις περιβάλλοντος του φλοιού, ενώ το /etc/bashrc περιέχει τους ρυθμίσεις για όλο το σύστημα για τις λειτουργίες του φλοιού και των ψευδωνύμων. Το αρχείο /etc/bashrc ίσως να αναφέρεται μέσα στο /etc/profile ή μέσα στα ατομικά αρχεία ρυμισης φλοιού του κάθε χρήστη.

Ο πηγαίος κώδικας του Bash περιέχει παραδείγματα αρχείων bashrc, ή μπορείτε να βρείτε ένα αντίγραφο στο /usr/share/doc/bash-2.05b/startup-files. Αυτό είναι ένα μέρος από το bashrc το οποίο συνοδεύει την τεκμηρίωση του φλοιού Bash:

 
alias ll='ls -l'
alias dir='ls -ba'
alias c='clear'
alias ls='ls --color'
 
alias mroe='more'
alias pdw='pwd'
alias sl='ls --color'
 
pskill()
{
        local pid
 
        pid=$(ps -ax | grep $1 | grep -v grep | gawk '{ print $1 }')
        echo -n "killing $1 (process $pid)..."
        kill -9 $pid
        echo "slaughtered."
}
 

Εκτός από γενικά ψευδώνυμα, περιέχει χρήσιμα ψευδώνυμα που επιτρέπουν τη λειτουργία ορισμένων εντολών ακόμη και όταν τις γράφετε λάθος. Θα συζητήσουμε τα ψευδώνυμα και στην Ενότητα 3.5.2. Το αρχείο περιέχει και μια συνάρτηση, τη pskill. Οι συναρτήσεις θα συχητηθούν στο Κεφάλαιο 11.


3.1.2. Ατομικά αρχεία ρύθμισης χρηστών

Note

Δεν έχω τέτοια αρχεία;!

αυτά τα αρχεία μπορεί να μην βρίσκονται ως προεπιλογή στον οικείο σας κατάλογο. Αν χρειάζεται, δημιουργείστα τα.


3.1.2.1. ~/.bash_profile

Αυτό είναι το προτιμώμενο αρχείο για τη εξατομικευμένη διαμόρφωση των περιβάλλοντος των χρηστών. Σε αυτό το αρχείο, οι χρήστες μπορούν να προσθέσουν επιλογές ρύθμισης ή να αλλάξουν τις προκαθορισμένες ρυθμίσεις:

 
franky~> cat .bash_profile
#################################################################
#                                                               #
#   .bash_profile file                                          #
#                                                              	#
#   Executed from the bash shell when you log in.               #
#                                                               #
#################################################################
 
source ~/.bashrc
source ~/.bash_login
case "$OS" in
  IRIX)
    stty sane dec
    stty erase
    ;;
#  SunOS)
#  stty erase
#    ;;
  *)
    stty sane
    ;;
esac

Ο συγκεκριμένος  χρήστης ρυθμίζει  το χαρακτήρα backpspace ανάλογα με το λειτουργικό σύστημα. Εκτός από αυτό, διαβάζονται τα αρχεία .bashrc και .bash_login .


3.1.2.2. ~/.bash_login

Αυτό το αρχείο περιλαμβάνει συγκεκριμένες ρυθμίσεις οι οποίες κανονικά εκτελούνται μόνο όταν κατά τη σύνδεση του χρήστη με στο σύστημα (σε κατάσταση κειμένου).   Στο παράδειγμα, το χρησιμοποιούμε για ν α διαμορφώσουμε την τιμή umask και για να παρουσιάσουμε μία λίστα από συνδεδεμένους χρήστες. Ο χρήστης επίσης λαμβάνει το ημερολόγιο του τρέχοντος μήνα:

 
#######################################################################
#                                                                     #
#   Bash_login file                                                   #
#                                                                     #
#   commands to perform from the bash shell at login time             #
#   (sourced from .bash_profile)                                      #
#                                                                     #
#######################################################################
#   file protection
umask 002       # all to me, read to group and others
#   miscellaneous
w
cal `date +"%m"` `date +"%Y"`

Αν δεν υπάρχει το αρχείο ~/.bash_profile, τότε διαβάζεται απ' ευθείας αυτό το αρχείο.


3.1.2.3. ~/.profile

Στην απουσία των αρχείων ~/.bash_profile και ~/.bash_login, διαβάζεται το αρχείο ~/.profile. Μπορεί να περιέχει τις ίδιες ρυθμίσεις, που τότε είναι προσβάσιμες και σε άλλους φλοιούς. Όμως προσέξτε γιατί άλλοι φλοιοί μπορεί να μην καταλαβαίνουν το συντακτικό του Bash.


3.1.2.4. ~/.bashrc

Σήμερα, όλο και πιο συχνά χρησιμοποιούμε ένα μη-διαλογικό φλοιό, λόγου χάρη όταν συνδεόμαστε σε κατάσταση γραφικής διεπαφής μέσω τερματικού X windows. Καθώς ανοίγουμε  ένα παράθυρο, ο χρήστης δεν χρειάζεται να παρέχει το όνομα χρήστη και τον κωδικό πρόσβασης: άρα δεν πραγματοποείται καμμία ταυτοποίηση. Όταν συμβαίνει αυτό το Bash αναζητά το αρχείο  ~/.bashrc, γι' αυτό και το αρχείο αυτό αναφέρεται σε όλα τα αρχεία διαβάζονται κατά τη σύνδεση, έστι ώστε δεν χρειάζετα να εισάγουμε τις ίδιες ρυθμίσεις σε πολλαπλά αρχεία.

Σε αυτό το αρχείο .bashrc του χρήστη, πρώτα διαβάζουμε το το αρχείο /etc/bashrc για όλο το σύστημα, ενώ στη συνέχεια ορίζουμε μερικά ψευδώνυμα και εκχωρούμε τιμές σε ορισμένες μεταβλητές που χρησιμοποιούνται σε προγράμματα: 

 
franky ~> cat .bashrc
# /home/franky/.bashrc
 
# Source global definitions
if [ -f /etc/bashrc ]; then
       . /etc/bashrc
 
fi
 
# shell options
 
set -o noclobber
 
# my shell variables
 
export PS1="\[\033[1;44m\]\u \w\[\033[0m\] "
export PATH="$PATH:~/bin:~/scripts"
 
# my aliases
 
alias cdrecord='cdrecord -dev 0,0,0 -speed=8'
alias ss='ssh octarine'
alias ll='ls -la'
 
# mozilla fix
 
MOZILLA_FIVE_HOME=/usr/lib/mozilla
LD_LIBRARY_PATH=/usr/lib/mozilla:/usr/lib/mozilla/plugins
MOZ_DIST_BIN=/usr/lib/mozilla
MOZ_PROGRAM=/usr/lib/mozilla/mozilla-bin
export MOZILLA_FIVE_HOME LD_LIBRARY_PATH MOZ_DIST_BIN MOZ_PROGRAM
 
# font fix
alias xt='xterm -bg black -fg white &'
 
# BitchX settings
export IRCNAME="frnk"
 
# THE END
franky ~>

Περισσότερα παραδείγματα μπορούν να βρεθούν στο πακέτο του Bash. Θυμηθείτε οτι μπορεί να απαιτούνται τροποποιήσεις των αρχείων για να δουλέψουν στο περιβλαλλον σας.

Τα ψευδώνυμα συζητώνται στην Ενότητα 3.5.


3.1.2.5. ~/.bash_logout

Αυτό το αρχείο περιέχει εντολές που σχετίζονται με τη διαδικασία αποσύνδεσης . Στο παράδειγμα, το παράθυρο τερματικού καθαρίζεται κατά την αποσύνδεση. Αυτό είναι χρήσιμο για απομακρυσμένες συνδέσεις, οι οποίες θα αφήσουν ένα κενό παράθυρο μετά το κλείσιμό τους.

 
franky ~> cat .bash_logout
#######################################################################
#                                                                     #
#   Bash_logout file                                                  #
#                                                                     #
#   commands to perform from the bash shell at logout time            #
#                                                                     #
#######################################################################
clear
franky ~>

3.1.3. Τροποποίηση των αρχείων ρύθμισης φλοιού

Όταν τροποποιούμε οποιοδήποτε από τα παραπάνω αρχεία, οι χρήστες πρέπει είτε να επανασυνδέονται με το σύστημα ή να εκτελούν την εντολή source στα τροποποημένα αρχεία για να ενεργοποιηθούν οι αλλαγές τους. Διερμηνεύοντας με αυτόν τον τρόπο το σενάριο, οι αλλαγές εφαρμόζονται στη τρέχουσα σύνοδο του φλοιού:

Εικόνα 3-1. Διαφορετικές προπτροπές για διαφορετικούς χρήστες

Εικόνα 3-1

Τα περισσότερα σενάρια φλοιού εκτελούνται σε ιδιωτικό περιβάλλον: οι μεταβλητές δεν κληρονομούνται σε θυγατρικές διεργασίες εκτός και αν εξάγονται ρητά (με export) από το γονικό φλοιό. Η εκτέλεση (ή διερμηνεία) ενός αρχείου που περιέχει εντολές φλοιού είναι ένας τρόπος να εφαρμόσουμε αλλαγές στο δικό μας περιβάλλον και να ρυθμίσουμε τις μεταβλητές του τρέχουσας συνόδου φλοιού.

Αυτό το παράδειγμα επίσης επιδεικνύει την χρήση των διαφορετικών ρυθμίσεων προτροπής για διαφορετικές χρήσεις. Σε αυτή τη περίπτωση, κόκκινο σημαίνει κίνδυνος. Όταν έχετε πράσινη προτροπή, τότε να μην ανησυχείτε πολύ.

Παρατηρήστε ότι το source resourcefile είναι το ίδιο με το . resourcefile.

Αν χαθείτε μέσα στα αρχεία ρύθμισης, και βρεθείτε αντιμέτωποι με ρυθμίσεις που η προέλευσή τους δεν είναι ξεκάθαρη, χρησιμοποιείστε προτάσεις echo, ακριβώς όπως στην εκσφαλμάτωση σεναρίων: Δείτε την Ενότητα 2.3.2. Ίσως προσθέσετε γραμμές σαν αυτήν:

 
echo "Now executing .bash_profile.."

ή σαν αυτήν:

 
echo "Now setting PS1 in .bashrc:"
export PS1="[some value]"
echo "PS1 is now set to $PS1"

3.2. Μεταβλητές

3.2.1. Τύποι μεταβλητών

Όπως είδατε στα παραπάνω παραδείγματα, τα ονόματα των μεταβλητών φλοιού γράφονται με κεφαλαίους χαρακτήρες κατά σύμβαση. Ο φλοιός Bash διατηρεί δύο τύπους μεταβλητών:


3.2.1.1. Καθολικές μεταβλητές

Οι καθολικές μεταβλητές ή μεταβλητές περιβάλλοντος είναι διαθέσιμες σε όλους τους φλοιούς. Οι εντολές env ή printenv μπορούν να χρησιμοποιηθούν για την εμφάνιση των μεταβήτών περιβάλλοντος (και των τιμών τους). Αυτά τα προγράμματα βρίσκονται στο πακέτο sh-utils.

Ακολουθεί μια τυπική εμφάνιση:

 
franky ~> printenv
CC=gcc
CDPATH=.:~:/usr/local:/usr:/
CFLAGS=-O2 -fomit-frame-pointer
COLORTERM=gnome-terminal
CXXFLAGS=-O2 -fomit-frame-pointer
DISPLAY=:0
DOMAIN=hq.xalasys.com
e=
TOR=vi
FCEDIT=vi
FIGNORE=.o:~
G_BROKEN_FILENAMES=1
GDK_USE_XFT=1
GDMSESSION=Default
GNOME_DESKTOP_SESSION_ID=Default
GTK_RC_FILES=/etc/gtk/gtkrc:/nethome/franky/.gtkrc-1.2-gnome2
GWMCOLOR=darkgreen
GWMTERM=xterm
HISTFILESIZE=5000
history_control=ignoredups
HISTSIZE=2000
HOME=/nethome/franky
HOSTNAME=octarine.hq.xalasys.com
INPUTRC=/etc/inputrc
IRCNAME=franky
JAVA_HOME=/usr/java/j2sdk1.4.0
LANG=en_US
LDFLAGS=-s
LD_LIBRARY_PATH=/usr/lib/mozilla:/usr/lib/mozilla/plugins
LESSCHARSET=latin1
LESS=-edfMQ
LESSOPEN=|/usr/bin/lesspipe.sh %s
LEX=flex
LOCAL_MACHINE=octarine
LOGNAME=franky
LS_COLORS=no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:bd=40;33;01:cd=40;33;01:or=01;05;37;41:mi=01;05;37;41:ex=01;32:*.cmd=01;32:*.exe=01;32:*.com=01;32:*.btm=01;32:*.bat=01;32:*.sh=01;32:*.csh=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.bz=01;31:*.tz=01;31:*.rpm=01;31:*.cpio=01;31:*.jpg=01;35:*.gif=01;35:*.bmp=01;35:*.xbm=01;35:*.xpm=01;35:*.png=01;35:*.tif=01;35:
MACHINES=octarine
MAILCHECK=60
MAIL=/var/mail/franky
MANPATH=/usr/man:/usr/share/man/:/usr/local/man:/usr/X11R6/man
MEAN_MACHINES=octarine
MOZ_DIST_BIN=/usr/lib/mozilla
MOZILLA_FIVE_HOME=/usr/lib/mozilla
MOZ_PROGRAM=/usr/lib/mozilla/mozilla-bin
MTOOLS_FAT_COMPATIBILITY=1
MYMALLOC=0
NNTPPORT=119
NNTPSERVER=news
NPX_PLUGIN_PATH=/plugin/ns4plugin/:/usr/lib/netscape/plugins
OLDPWD=/nethome/franky
OS=Linux
PAGER=less
PATH=/nethome/franky/bin.Linux:/nethome/franky/bin:/usr/local/bin:/usr/local/sbin:/usr/X11R6/bin:/usr/bin:/usr/sbin:/bin:/sbin:.
PS1=\[\033[1;44m\]franky is in \w\[\033[0m\]
PS2=More input>
PWD=/nethome/franky
SESSION_MANAGER=local/octarine.hq.xalasys.com:/tmp/.ICE-unix/22106
SHELL=/bin/bash
SHELL_LOGIN=--login
SHLVL=2
SSH_AGENT_PID=22161
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
SSH_AUTH_SOCK=/tmp/ssh-XXmhQ4fC/agent.22106
START_WM=twm
TERM=xterm
TYPE=type
USERNAME=franky
USER=franky
_=/usr/bin/printenv
VISUAL=vi
WINDOWID=20971661
XAPPLRESDIR=/nethome/franky/app-defaults
XAUTHORITY=/nethome/franky/.Xauthority
XENVIRONMENT=/nethome/franky/.Xdefaults
XFILESEARCHPATH=/usr/X11R6/lib/X11/%L/%T/%N%C%S:/usr/X11R6/lib/X11/%l/%T/%N%C%S:/usr/X11R6/lib/X11/%T/%N%C%S:/usr/X11R6/lib/X11/%L/%T/%N%S:/usr/X11R6/lib/X11/%l/%T/%N%S:/usr/X11R6/lib/X11/%T/%N%S
XKEYSYMDB=/usr/X11R6/lib/X11/XKeysymDB
XMODIFIERS=@im=none
XTERMID=
XWINHOME=/usr/X11R6
X=X11R6
YACC=bison -y

3.2.1.2. Τοπικές μεταβλητές

Οι τοπικές μεταβλητές είναι διαθέσιμες μόνο στο τρέχοντα φλοιό. Με την εσωτερική εντολή set χωρίς άλλες επιλογές εμφανίζουμε όλες τις μεταβλητές (και τις μεταβλητές περιβάλλοντος) καθώς και τις συναρτήσεις. Η έξοδος είναι ταξινομημένη σύμφωνα με την επιλεγμένη γλώσσα και είναι εύκολα επαναχρησιμοποιήσιμη.

Ακολουθεί ένα αρχείο diff (διαφορών) που δημιουργήθηκε συγκρίνοντας τις εξόδους των εντολών printenv και set, μετά την αφαίρεση των συναρτήσεων τις οι οποίες εμφανίζει ηνεντολή set:

 
franky ~> diff set.sorted printenv.sorted | grep "<" | awk '{ print $2 }'
BASE=/nethome/franky/.Shell/hq.xalasys.com/octarine.aliases
BASH=/bin/bash
BASH_VERSINFO=([0]="2"
BASH_VERSION='2.05b.0(1)-release'
COLUMNS=80
DIRSTACK=()
DO_FORTUNE=
EUID=504
GROUPS=()
HERE=/home/franky
HISTFILE=/nethome/franky/.bash_history
HOSTTYPE=i686
IFS=$'
LINES=24
MACHTYPE=i686-pc-linux-gnu
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PIPESTATUS=([0]="0")
PPID=10099
PS4='+
PWD_REAL='pwd
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
THERE=/home/franky
UID=504

 

Note

Awk

Η γλώσσα προγραμματισμού GNU Awk εξηγείται στο Κεφάλαιο 6.


3.2.1.3. Περιεχόμενο μεταβλητών

Εκτός από τη διάκριση των μεταβλητών σε καθολικές και τοπικές, μπορούμε να τις ταξινομήσουμε σε κατηγορίες συμφωνα με το περιεχόμενό τους. Από αυτή την άποψη, οι μεταβλητές χωρίζονται σε 4 τύπους :

·         Συμβολοσειρές (αλφαριθμητικά, string)

·         Ακέραιοι

·         Σταθερές 

·         Πίνακες μεταβλητών

Θα συζητήσουμε τους τύπους στο Κεφάλαιο 10. Προς το παρόν, θα εργαστούμε με ακέραιους και συμβολοσειρές.


3.2.2. Δημιουργία μεταβλητών

Τα ονόματα των μεταβλητών είναι ευαίσθητα στη διάκριση μεταξύ πεζών και κεφαλαίων, ενώ οι προεπιλεγμένες μεταβλητές έχουν ονόματα με κεφαλαία γράμαμτα. Συνηθίζεται, χωρίς όμως να είναι υποχρεωτικό, να δίννουμε στις τοπικές μεταβλητές ονόματα με πεζά γράμματα. Τα ονόματα των μεταβλητών μπορούν να περιέχουν ψηφία, αλλά όχι σαν πρώτο χαρακτήρα του ονόματος.

 
prompt> export 1number=1
bash: export: `1number=1': not a valid identifier

Για να ορίσουμε μια μεταβλητή στο φλοιό, γράφουμε:

VARNAME="value"

Αν αφήσουμε κενά πριν ή μετά το ίσον θα προκαλέσουμε σφάλματα. Μια καλή συνήθεια είναι να περικλείουμε τη τιμή της μεταβλητής σε διπλά εισαγωγικά (όπως τις συμβολοσειρές) έτσι ώστε να μην υπάρχει περίπτωση σφάλματος.

Παρακάτω δίνονται μερικά περαδείγματα:

 
franky ~> MYVAR1="2"
 
franky ~7gt; echo $MYVAR1
2
 
franky ~> first_name="Franky"
 
franky ~> echo $first_name
Franky
 
franky ~> full_name="Franky M. Singh"
 
franky ~> echo $full_name
Franky M. Singh
 
franky ~> MYVAR-2="2"
bash: MYVAR-2=2: command not found
 
franky ~> MYVAR1 ="2"
bash: MYVAR1: command not found
 
franky ~> MYVAR1= "2"
bash: 2: command not found
 
franky ~> unset MYVAR1 first_name full_name
 
franky ~> echo $MYVAR1 $first_name $full_name
<--no output-->
 
franky ~>

3.2.3. Εξαγωγή μεταβλητών

Μια μεταβλητή που δημιουργήθηκε όπως παραπάνω είναι διαθέσιμη μόνο στον τρέχοντα φλοιό. Είναι μία τοπική μεταβλητή: οι θυγατρικές διεργασίες του τρέχοντος φλοιού δεν θα γνωρίζουν αυτή τη μεταβλητή. Για να περάσουμε τις μεταβλητές σε ένα υποφλοιό (ή γενικά μια θυγατρική διεργασία), πρέπει να τις εξάγουμε χρησιμοποιώντας την εσωτερική εντολή export. Οι μεταβλητές οι οποίες εξάγονται αναφέρονται ως μεταβλητές περιβάλλοντος. Η δημιουργία και εξαγωγή μπορεί να γίνει σε ένα βήμα:

export VARNAME="value"

Ένας υποφλοιός (θυγατρική διεργασία) μπορεί να αλλάξει τις μεταβλητές που κληρονομεί από την γονική διεργασία, αλλά οι αλλαγές που συμβαίνουν στη θυγατρική δεργασία δεν επηρεάζουν τη γονική. Αυτό φαίνεται στο παράδειγμα:

 
franky ~> full_name="Franky M. Singh"
 
franky ~> bash
 
franky ~> echo $full_name
 
 
franky ~> exit
 
franky ~> export full_name
 
franky ~> bash
 
franky ~> echo $full_name
Franky M. Singh
 
franky ~> export full_name="Charles the Great"
 
franky ~> echo $full_name
Charles the Great
 
franky ~> exit
 
franky ~> echo $full_name
Franky M. Singh
 
franky ~>

Όταν τη πρώτη φορά προσπαθούμε να διαβάσουμε την τιμή της full_name σε ένα υποφλοιό, δεν υπάρχει εκεί (η echo δείχνει μια κενή συμβολοσειρά). Ο υποφλοιός τερματίζεται, και το full_name εξάγεται από τη γονική διεργασία – μια μεταβλητή μπορεί να εξαχθεί μόνο αφού της έχει εκχωρηθεί μια τιμή. Στη συνέχεια ένας νέος υποφλοιός ξεκινάει, στον οποίο η εξαχθείσα μεταβλητή είναι ορατή. Η τιμή της μεταβλητής μεταβάλλεται, και ταυτόχρονα εξάγεται σε μελλοντικές θυγατρικές διεργασίες του υποφλοιού. Όμως, για τη γονική διεργασία η τιμή της μεταβλητής παραμένει η ίδια.


3.2.4. Δεσμευμένες μεταβλητές

3.2.4.1. Δεσμευμένες μεταβλητές του φλοιού Bourne 

Το Bash χρησιμοποιεί ορισμένες μεταβλητές φλοιού με τον ίδιο τρόπο  όπως ο φλοιός Bourne. Σε μερικές περιπτώσεις, το Bash εκχωρεί μια προεπιλεγμένη τιμή σε μία μεταβλητή. Ο πίνακας δίνει μία σύνοψη αυτών των μεταβλητών του απλού φλοιού:

Πίνακας 3-1. Δεσμευμένες μεταβλητές του φλοιού Bourne 

Όνομα μεταβλητής

Ορισμός

CDPATH

Μια λίστα από ονόματα καταλόγων διαχωρισμένων με το σύμβολο :  που χρησιμοποιείται από την εσωτερική εντολή cd

HOME

Ο οικείος κατάλογος του τρέχοντος χρήστη: η προεπιλογή της εντολής cd. Η τιμή αυτής της μεταβλητής επίσης χρησιμοποιεί την επέκταση της  ~

IFS

Λίστα διαχωριστικών χαρακτήρων: χρησιμοποιούνται από τον φλοιό κατά τις επεκτάσεις.

MAIL

Αν η μεταβλητή οριστεί με ένα όνομα αρχείου και η μεταβλητή MAILPATH δεν έχει οριστεί, τότε  το Bash ενημερώνει το χρήστη για την έλευση της αλληλογραφίας στο συγκεκριμένο αρχείο.

MAILPATH

Μια λίστα ονομάτων αρχείων διαχωρισμένων με το σύμβολο : που ελέγχει ο φλοιός περιοδικά για νέα αλληλογραφία.

OPTARG

Η τιμή του τελευταίου ορίσματος επιλογής που επεξεργάστηκε η εσωτερική εντολή getopts.

OPTIND

Ο αριθμοδείκτης του τελευταίου ορίσματος επιλογής που επεξεργάστηκε η εσωτερική εντολή getopts.

PATH

Μια λίστα από ονόματα καταλόγων διαχωρισμένα με το σύμβολο :  που χρησιμοποιείται από το φλοιό για την αναζήτηση εντολών.

PS1

Η βασική προτροπή: η προεπιλεγμένη τιμή είναι "'\s-\v\$ '".

PS2

Η δευτρεύουσα προτροπή: η προεπιλεγμένη τιμή είναι "'> '".


3.2.4.2. Δεσμευμένες μεταβλητές του Bash 

Αυτές οι ματαβλητές ορίζονται από το Bash, οι άλλοι φλοιοί κανονικά δεν τις χειρίζονται με ιδιαίτερο τρόπο.

Table 3-2. Δεσμευμένες μεταβλητές του Bash

Όνομα μεταβλητής

Ορισμός

auto_resume

Αυτή η μεταβλητή ελέγχει πως ο φλοιός διαδρά με τον χρήστη και με τον έλεγχο εργασιών.

BASH

Ολόκληρο το όνομα της διαδρομής που χρησιμοποιείται για την εκτέλεση του τρέχοντος στιγμιοτύπου του Bash.

BASH_ENV

Αν αυτή η μεταβλητή οριστεί, όταν το Bash καλείται να εκτελέσει ένα σενάριο φλοιού, η τιμή της μεταβλητής επεκτείνεται και χρησιμοποιείται ως όνομα ενός αρχείου εκκίνησης που διαβάζεται πριν από την εκτέλεση του σεναρίου.

BASH_VERSION

Ο αριθμός έκδοσης του τρέχοντος στιγμιοτύπου του Bash.

BASH_VERSINFO

Μια μεταβλητή πίνακα μόνο για ανάγνωση της οποίας τα μέλη της διατηρούν πληροφορίες έκδοσης για το τρέχον στιμιότυπο του Bash.

COLUMNS

Χρησιμοποιείται από την εσωτερική εντολή select για να καθορίσει το πλάτος του τερματικού όταν εμφανίζει λίστες επιλογής. Ορίζεται αυτόματα ορίζει με τη λήψη του σήματος SIGWINCH.

COMP_CWORD

Ένας αριθμοδείκτης μέσα στο ${COMP_WORDS} της λέξης που περιέχει την τρέχουσα θέση του δρομέα

COMP_LINE

Η τρέχουσα γραμμή εντολών.

COMP_POINT

Ο αριθμοδείκτης τής τρέχουσας θέσης του δρομέα σε σχέση με την αρχή της τρέχουσας εντολής.

COMP_WORDS

Μια μεταβλητή τύπου πίνακα όπου υπάρχει σε διακεκριμένες λέξεις (tokens) η τρέχουσα γραμμή εντολών.

COMPREPLY

Μια μεταβλητή τύπου πίνακα από την οποία το Bash διαβάζει τις πιθανές συμπληρώσεις που δημιουργούνται από μια συνάρτηση φλοιού που υλοποιεί τη συμπλήρωση γραμμής εντολών (με Tab).

DIRSTACK

Μια μεταβλητή τύπου πίνακα που περιέχει τα τρέχοντα περιεχόμενα της στοίβας καταλόγων.

EUID

Το εκετελστικό ID του τρέχοντος χρήστη.

FCEDIT

Ο συντάκτης κειμένου που χρησιμοποιείται από την επιλογή -e στην εωτερική εντολή fc.

FIGNORE

Λίστα επιθεμάτων χωρισμένων με το σύμβολο :τα οποία αγνοούνται όταν υλοποιείται συμπλήρωση ονομάτων αρχείων.

FUNCNAME

Το όνομα της τρέχουσας εκτελούμενης συνάρτησης του φλοιού.

GLOBIGNORE

Μια λίστα προτύπων  χωρισμένων με το σύμβολο : που ορίζουν τα ονόματα του αρχείου που αγνοούνται κατά την επέκταση ονομάτων αρχέιων.

GROUPS

Μια μεταβλητή τύπου πίνακα που περιέχει την λίστα των ομάδων στις οποίες ο τρέχων χρήστης είναι μέλος.

HISTCHARS

Μέχρι τρεις χαρακτήρες που ελέγχουν τη επέκταση του ιστορικού, γρήγορη υποκατάσταση και το tokenization.

HISTCMD

Ο αριθμός ιστορικού, ή ο αριθμοδείκτης στη λίστα ιστορικού, της τρέχουσας εντολής.

HISTCONTROL

Καθορίζει εάν μία εντολή προστέθηκε στο αρχείο ιστορικού.

HISTFILE

Το όνομα του αρχείου του οποίου το ιστορικό εντολών έχει σωθεί. Η προεπιλεγμένη τιμή είναι ~/.bash_history.

HISTFILESIZE

Ο μέγιστος αριθμός γραμμών που περιέχεται στο αρχείο ιστορικού, προεπιλεγμένος σε  500.

HISTIGNORE

Μια λίστα από πρότυπα χωρισμένα με το συμβολο : που χρησιμοποιούνται για να αποφασισιστεί ποιες γραμμές εντολών πρέπει να αποθηκευθουν στη λίστα ιστορικού.

HISTSIZE

Ο μέγιστος αριθμός από εντολές που ενθυμούνται στη λίστα του ιστορικού, προεπιλεγμένος σε 500.

HOSTFILE

Περιέχει το όνομα αρχείου με την ίδια μορφή όπως το /etc/hosts το οποίο διαβάζεται όταν ο φλοιός χρειάζεται να συμπληρώσει ένα  το όνομα ενός διακομιστή.

HOSTNAME

Το όνομα του τρέχοντος υπολογιστή.

HOSTTYPE

Ένα αλφαριθμητικό που περιγράφει τον τύπο του τρέχοντος υπολογιστή.

IGNOREEOF

Ελέγχει την δράση του φλοιού εάν ληφθεί ένας EOF χαρακτήρας ως μοναδική είσοδος.

INPUTRC

Το όνομα του αρχείου Readline, που υπερβαίνει την προεπιλογή /etc/inputrc.

LANG

Χρησιμοποιείται για να καθορίσει τη γλώσσα (περιοχή) για κάθε περίπτωση που δεν έχει επιλεγεί με τη μεταβλητή που ξεκινά με LC_.

LC_ALL

Αυτή η μεταβλητή αντικαθιστά τη τιμή από τη LANG και απ'ο κάθε άλλη LC_ μεταβλητή.

LC_COLLATE

Αυτή η μεταβλητή καθορίζει τη σειρά αντιπαραβολής που χρησιμοποιείται όταν ταξινομούνται τα αποτελέσματα από την επέκταση ονόματος αρχείου, και καθορίζει τη συμπεριφορά του εύρους των παραστάσεων, με ισοδύναμες κλάσεις, κατά την επέκταση ονόματος αρχείου και αναγνώριση προτύπων..

LC_CTYPE

Αυτή η μεταβλητή καθορίζει την ερμηνεία των χαρακτήρων και τη συμπεριφορά των κλάσεων του χαρακτήρα κατά την επέκταση ονόματος του αρχείου και αναγνώριση προτύπων.

LC_MESSAGES

Αυτή η μεταβλητή καθορίζει τη περιοχή (χώρα) που χρησιμοποιείται να μεταφράσει τις συμβολοσειρές σε διπλά εισγωγικά και με σύμβολο"$" μπροστά. .

LC_NUMERIC

Αυτή η μεταβλητή καθορίζει την περιοχή (χώρα) που χρησιμοποιείτε για τον αριθμό μορφοποίησης.

LINENO

Ο αριθμός γραμμής σε ένα σενάριο ή η συνάρτηση φλοιού που εκτελείται επί του παρόντος.

LINES

Χρησιμοποιείτε από την εσωτερική εντολή  select για να καθορίσει το μήκος της στήλης για την εκτύπωση των λιστών επιλογής.

MACHTYPE

Μια συμβολοσειρά που περιγράφει πλήρως το τύπο του συστήματος στο οποίο εκτελείται το Bash, στη  επίσημη GNU CPU-COMPANY-SYSTEM μορφή.

MAILCHECK

Πόσο συχνά (σε δευτερόλεπτα) όπου ο φλοιός θα πρέπει να ελέγχει για αλληλογραφία στα αρχεία που καθορίζονται μέσα στις μεταβλητές MAILPATH ή MAIL.

OLDPWD

Ο προηγούμενος τρέχων κατάλογος που ορίζεται από τηνεσωτερική εντολή cd.

OPTERR

Αν οριστεί η τιμή 1, το  Bash προβάλει μηνύματα λάθους που παράγει η εσωτερική εντολή getopts.

OSTYPE

Ένα αλφαριθμητικό που περιγράφει το λειτουργικό σύστημα που εκτελείται το Bash .

PIPESTATUS

μία μεταβλητή τύπου πίνακα που περιέχει μία λίστα από τιμές κατάστασης εξόδου των διεργασιών  από τη πιο πρόσφατα εκτελεσμένη σωλήνωση προσκηνίου. (οι οποίες ίσως να περιέχουν μόνο μια μοναδική εντολή).

POSIXLY_CORRECT

Αν αυτή η μεταβλητή είναι στο περιβάλλον όταν ξεκινά το bash, τότε ο φλοιός εσέρχεται σε κατάσταση POSIX.

PPID

Το ID της της γονικής διεργασίας του τρέχοντος φλοιού .

PROMPT_COMMAND

Αν οριστεί, τότε η τιμή ερμηνεύεται ως μία εντολή προς εκτέλεση πριν από την εκτύπωση της κάθε βασικής προτροπής (PS1).

PS3

Η τιμή αυτής της μεταβλητής χρησιμοποιείται ως προτροπή για την  εντολή select. Προεπιλογή ως "'#? '"

PS4

Η τιμή είναι μία προτροπή που εμφανίζεται στη γραμμή εντολών όταν έχει οριστεί η επιλογή -x: Προεπιλογή ως "'+ '".

PWD

Ο  τρέχων κατάλογος εργασίας που ορίζεται από την εσωτερική εντολή cd.

RANDOM

Κάθε φορά που αναφέρεται αυτή η μεταβλητή, δημιουργείται μία τυχαία μεταβλητή μεταξύ του 0 και 32767. Η τιμή που τίθεται αρχικά στην μεταβλητή χρησιμοποιείται  ως seed..

REPLY

Η προεπιλεγμένη μεταβλητή για την εσωτερική εντολή read.

SECONDS

Αυτή η μεταβλητή κρατά τον αριθμό των δευτερολέπτων από τότε που ξεκίνησε ο φλοιός.

SHELLOPTS

Μια λίστα των ενεργοποιημένων επιλογών του φλοιού, χωρισμένων με :.

SHLVL

Αυξάνεται κατά ένα κάθε φορά που ένα νέο στιγμιότυπο του Bash ξεκινά.

TIMEFORMAT

Η τιμή αυτής της παραμέτρου χρησιμοποιείται ως ένα αλφαριθμητικό μορφοποίησης των πληροφοριών χρονιμού για σωληνώσεις με το πρόθεμα time.

TMOUT

Αν οριστεί μία τιμή μεγαλύτερη από ότι το μηδέν, η TMOUT συμπεριφέρεται όπως η προεπιλεγμένη timeout για την εσωτερική εντολή read. Σε ένα διαλογικό φλοιό, η τιμή ερμηνεύεται ως ο αριθμός από δευτερόλεπτα που περιμένει για εισαγωγή μετά από την εμφάνιση της βασικής προτροπής. Αν, μετά από ένα αριθμό δευτερολέπτων δεν υπάρχει είσοδος το Bash τερματίζει.

UID

Το πραγματικό ID του τρέχοντος χρήστη.

Ελέγξτε το man του Bash, για πληροφορίες ή σελίδες doc για εκτεταμένες πληροφορίες. Μερικές μεταβλητές είναι μόνο για ανάγνωση, μερικές ορίζονται αυτόματα και μερικές χάνουν την σημασία τους θέτοντας τιμή διαφορετική από την προεπιλεγμένη.


3.2.5. Ειδικές παράμετροι

Ο φλοιός μεταχειρίζεται ορισμένες μεταβλητές με ειδικό τρόπο. Αυτές οι μεταβλητές (ή παράμετροι) μπορούν μόνο να διαβαστούν,  δεν επιτρέπεται η ανάθεση τιμών σε αυτές.

Πίνακας 3-3. Ειδικές μεταβλητές του Βash

Χαρακτήρας

Ορισμός

$*

Επεκτείνει μία παράμετρο θέσης, ξεκινώντας από το ένα. Όταν η επέκταση βρίσκεται μέσα σε διπλά εισαγωγικά, επεκτείνεται σε ξεχωριστές παραμέτρους με βάση τον πρώτο χαρακτήρα από την ειδική μεταβλητή IFS.

$@

Επεκτείνει μία παράμετρο θέσης, ξεκινώντας από το ένα. Όταν η επέκταση βρίσκεται μέσα σε διπλά εισαγωγικά, κάθε λέξη επεκτείνεται σε ξεχωριστή παράμέτρο.

$#

Επεκτείνει τον αριθμό των παραμέτρων θέσης σε δεκαδική μορφή.

$?

Επεκτείνει την κατάσταση εξόδου της πιο πρόσφατα εκταλεσμένης σωλήνωσης..

$-

Επεκτείνεται στις τρέχουσες επιλογές είτε όπως ορίστηκαν στην κλήση, ειίτε από την εσωτερική εντολή set,ή από τον ίδιο το φλοιό (όπως το -i).

$$

Επεκτείνεται στο ID διαργασίας του φλοιού..

$!

Επεκτείνεται στοs ID γασίας της πιο πρόσφατα εκετελεσμένης εντολής παρασκηνίου.

$0

Επεκτείνεται στο όνομα του φλοιού ή του σεναρίου που εκτελείται.

$_

Η μεταβλητή ορίζεται στην εκκίνηση του φλοιού και περιέχει το απόλυτο όνομα αρχείου φλοιού ή σεναρίου που εκτελείται όπως περνιέται στη λίστα ορισμάτων. Συνακόλουθα , επεκτείνεεται στο τελευταίο όρισμα της προηγούμενης εντολής, μετά την επέκταση. Επίσης ορίζει το απόλυτο όνομα διαδρομής κάθε εντολής που εκτελέστηκε  και τοποθετήθηκε στο περιβάλλον που εξάγεται από την εντολή. Όταν ελέγχουμε την αλληλογραφία, αυτή η παράμετρος διατηρεί το όνομα του αρχείου αλληλογραφίας.

Οι παράμετροι θέσης είναι οι λέξεις που ακολουθούν το όνομα του σεναρίου φλοιού. Αυτές τοποθετούνται στις μεταβλητές $1, $2, $3  κλπ.  Εφόσον χρειαστεί, οι μεταβλητές τοποθετούνται σε έναν εσωτερικό πίνακα. Η παράμτερος $# διατηρεί το συνολικό αριθμό των παραμέτρων, όπως φαίνεται στο παρακάτω απλό σενάριο:

 
#!/bin/bash
 
# positional.sh
# This script reads 3 positional parameters and prints them out.
 
POSPAR1="$1"
POSPAR2="$2"
POSPAR3="$3"
 
echo "$1 is the first positional parameter, \$1."
echo "$2 is the second positional parameter, \$2."
echo "$3 is the third positional parameter, \$3."
echo
echo "The total number of positional parameters is $#."

Στην εκτέλεση μπορείτε να δώσετε οποιοδήποτε αριθμό ορισμάτων:

 
franky ~> positional.sh one two three four five
one is the first positional parameter, $1.
two is the second positional parameter, $2.
three is the third positional parameter, $3.
 
The total number of positional parameters is 5.
 
franky ~> positional.sh one two
one is the first positional parameter, $1.
two is the second positional parameter, $2.
 is the third positional parameter, $3.
 
The total number of positional parameters is 2.

Περισσότερα για τη χρήση αυτών των παραμέτρων στο Κεφάλαιο 7 και στην Ενότητα 9.7.

Μερικά παραδείγματα των άλλων ειδικών παραμέτρων:

 
franky ~> grep dictionary /usr/share/dict/words
dictionary
 
franky ~> echo $_
/usr/share/dict/words
 
franky ~> echo $$
10662
 
franky ~> mozilla &
[1] 11064
 
franky ~> echo $!
11064
 
franky ~> echo $0
bash
 
franky ~> echo $?
0
 
franky ~> ls doesnotexist
ls: doesnotexist: No such file or directory
 
franky ~> echo $?
1
 
franky ~>

Ο χρήστης franky ξεκινά με την εντολή grep, που έχει ως αποτέλεσμα τον ορισμό της μεταβλητής _ . Το ID διεργασίας αυτού του φλοιού είναι 10662. Αφού τοποθετήσουμε μια δουλειά στο παρασκήνιο, η μεταβλητή ! κρατά το ID της διεργασίας παρασκηνίου. Η διεργασία που εκτελέιται είναι το bash. Όταν γίνει κάποιο σφάλμα η μεταβλητή ? έχει τιμή διάφορη του μηδενός.


3.2.6. Ανακύκλωση σεναρίων με μεταβλητές

Εκτός από το να κάνουμε το σενάριο πιο ευανάγνωστο, οι ματαβλητές μας επιτρέπευν να εφαρμόσυμε το ίδιο σενάριο σε διαφορετικά περιβάλλοντα ή για άλλο σκοπό. Θεωρείστε το ακόλουθο παράδειγμα, ένα πολύ απλό σενάριο που δημιουργεί ένα εφεδρικό αντίγραφο του οικείου καταλόγου του franky σε ένα απομακρυσμένο διακομιστή:

 
#!/bin/bash
 
# This script makes a backup of my home directory.
 
cd /home
 
# This creates the archive
tar cf /var/tmp/home_franky.tar franky > /dev/null 2>&1
 
# First remove the old bzip2 file.  Redirect errors because this generates some if the archive
# does not exist.  Then create a new compressed file.
rm /var/tmp/home_franky.tar.bz2 2> /dev/null
bzip2 /var/tmp/home_franky.tar
 
# Copy the file to another host - we have ssh keys for making this work without intervention.
scp /var/tmp/home_franky.tar.bz2 bordeaux:/opt/backup/franky > /dev/null 2>&1
 
# Create a timestamp in a logfile.
date > /home/franky/log/home_backup.log
echo backup succeeded > /home/franky/log/home_backup.log

Πρώτα από όλα, είναι πολύ πιθανό να κάνετε λάθη αν ονομάζετε τα αρχεία και τους καταλόγους με το χέρι κάθε φορά που τα χρειάζεστε. Δεύτερο, υποθέστε ότι ο franky θέλει να δώσει αυτό το σενάριο στη carol, τότε η  carol θα πρέπει να κάνει σχεδόν τις ίδιες διορθώσεις πριν χρησιμοποιήσει το σενάριο για να αντιγράψει το προσωπικό της κατάλογο. Το ίδιο συμβαίνει αν ο franky θέλει να χρησιμοποιήσει το σενάριο για την αντιγραφή άλλων καταλόγων. Για εύκολη ανακύκλωση, κάντε όλα τα αρχεία, καταλόγους, όνομα χρηστη, ονόμα διακομιστή, κλπ μεταβλητές. Έτσι, χρειάζεστε να τροποποιήσετε το σενάριο σε ένα μόνο τμήμα του, χωρίς να πρέπει να ελέγξετε ολόκληρο του σενάριο κάθε φορά. Να ένα παράδειγμα:

 
#!/bin/bash
                                                                                                 
# This script makes a backup of my home directory.
 
# Change the values of the variables to make the script work for you:
BACKUPDIR=/home
BACKUPFILES=franky
TARFILE=/var/tmp/home_franky.tar
BZIPFILE=/var/tmp/home_franky.tar.bz2
SERVER=bordeaux
REMOTEDIR=/opt/backup/franky
LOGFILE=/home/franky/log/home_backup.log
 
cd $BACKUPDIR
 
# This creates the archive
tar cf $TARFILE $BACKUPFILES > /dev/null 2>&1
                                                                                                 
# First remove the old bzip2 file.  Redirect errors because this generates some if the archive 
# does not exist.  Then create a new compressed file.
rm $BZIPFILE 2> /dev/null
bzip2 $TARFILE
 
# Copy the file to another host - we have ssh keys for making this work without intervention.
scp $BZIPFILE $SERVER:$REMOTEDIR > /dev/null 2>&1
 
# Create a timestamp in a logfile.
date > $LOGFILE
echo backup succeeded > $LOGFILE

 

Note

Μεγάλοι κατάλογοι και μικρό εύρος ζώνης

Το παραπάνω είναι απλώς ένα παράδειγμα που ο καθένας μπορεί να το καταλάβει, χρησιμοποιεί ένα μικρό κατάλογο και ένα διακομιστή στο ίδιο το υποδίκτυο.Ανάλογα με το εύρος ζώνης σας, το μέγεθος του καταλόγου και την τοποθεσία του απομακρυσμένου διακομιστή, η αντιγραφή με αυτό το μηχανισμό μπορεί να πάρει υπερβολικά πολλή ώρα. Για μεγαλύτερους καταλόγους και χαμηλότερο εύρος ζώνης, χρησιμοποιήστε το rsync για να διατηρήσετε τους δύο καταλόγους συγχρονισμένους.


3.3. Χαρακτήρες σε εισαγωγικά

3.3.1. Γιατί;

Mερικοί χαρακτήρες έχουν διαφορετικό νόημα σε διαφορετικά συμφραζόμενα. Τα εισαγωγικά χρησιμοποιούνται για να αφαιρέσουν την ειδική σημασία από χαρακτήρες ή λέξεις: τα εισαγωγικά ακυρώνουν τους ειδικούς χειρισμούς σε χαρακτήρες, αποτρέπουν την αναγνώριση δεσμευμένων λέξεων και ακυρώνουν την επέκταση παραμέτρων.


3.3.2. Χαρακτήρες διαφυγής

Οι χαρακτήρες διαφυγής χρησιμοποιούνται για την αφαίρεση ειδικής σημασίας από μεμονωμένους χαρακτήρες. Στο Bash ο χαρακτήρας διαφυγής είναι το backslash \. Διατηρεί την κυριολεκτική τιμή του χαρακτήρα, με εξαίρεση την αλλαγή γραμμής (newline). Αν αμέσως μετά το backslash εμφανίζεται χαρακτήρας αλλαγής γραμμής, τότε αυτό σημαίνει συνέχεια της ίδιας εντολής σε νέα γραμμή. Το backslash αφαιρείται μαζί με την αλλαγή γραμμής δεν λαμβάνεται υπ' όψη στην είσοδο.

 
franky ~> date=20021226
 
franky ~> echo $date
20021226
 
franky ~> echo \$date
$date

Σε αυτό το παράδειγμα, η μεταβλητή date δημιουργήθηκε και πήρε μια τιμή. Η πρώτη εντολή echo εμφανίζει τη τιιμή της μεταβλητής, αλλά στη δέυτερη η σημασία του $ (περιεχόμενο) ακυρώνεται.


3.3.3. Απλά εισαγωγικά

Τα απλά εισαγωγικά ('') χρησιμοποιούνται για την ακύρωση ειδικής σημασίας ομάδας χαρακτήρων που βρίσκονται μεταξύ των εισαγωγικών (σαν ο κάθε χαρακτήρας να είχε μπροστά του backslash). Ένα απλό εισαγωγικό δεν μπορεί να βρεθεί μεταξύ δύο απλών εισαγωγικών, ακόμη και αν προηγείται backslash.

Συνεχίζουμε στο ίδιο παράδειγμα:

 
franky ~> echo '$date'
$date

3.3.4. Διπλά εισαγωγικά

Με τα διπλά εισαγωγικά οι χαρακτήρες διατηρούν την κυριoλεκτική τιμή τους, εκτός από το δολλάριο, τα ανάποδα εισαγωγικά (βαρείες, backticks ``) και το backslash.

Το δολλάριο και οι βαρείες διατηρούν την ειδική σημασία τους.

Το backslash διατηρεί τη σημασία του μόνο αν ακολουθείται από δολλάριο, βαρεία, διπλό εισαγωγικό, backslash ή αλλαγή γραμμής. Σε αυτές τις περιπτώσεις το backslash απλά αφαιρείται από τη συμβολοσειρά είσοδου. Στις υπόλοιπες περιπτώσεις το backslash δεν τροποποείται και υφίσταται κανονική επεξεργασία από τον διερμηνέα του φλοιού.

Ένα διπλό εισαγωγικό μπορεί να βρίσκεται μεταξύ διπλών εισαγωγικών αρκεί να προηγείται backslash.

 
franky ~> echo "$date"
20021226
 
franky ~> echo "`date`"
Sun Apr 20 11:22:06 CEST 2003
 
franky ~> echo "I'd say: \"Go for it!\""
I'd say: "Go for it!"
 
franky ~> echo "\"
More input>"
 
franky ~> echo "\\"
\

3.3.5. ANSI-C εισαγωγικά

Λέξεις με τη μορφή "$'STRING'"υφίστανται ειδική μεταχείριση. Η λέξη επεκτείνεται σε συμβολοσειρά με τους χαρακτήρες που ακολουθούν backslash να αντικαθίστανται με βάση το πρότυπο της ANSI-C standard. Τα πρότυπα μπορούν να βρεθούν στη τεκμηρίωση του Bash.


3.3.6. Τοπικές γλωσσικές συμβάσεις (locales)

Ένα αλφαριθμητικό σε διπλά ειαγωγικά που ακολουθεί είναι δολλάριο θα μεταφραστεί με βάση τις τρέχουσες τοπικές γλωσσικές συμβάσεις (locales). Αν η τοπική γλψσσική σύμβαση σύμβαση είναι "C" ή "POSIX",το δολλάριο αγνοείται  Αν η συμβολοσειρά μετφραστεί και αντικατασταθεί, η νέα συμβολοσειρά μπαίνει σε διπλά εισαγωγικά.


3.4. Επέκταση φλοιού

3.4.1. Γενικά

Αφού η γραμμή εντολών διασπαστεί σε σύμβολα (tokens) (δείτε Ενότητα 1.4.1.1), τα σύμβολα αυτά επεκτείνονται και αντικαθίστανται. Υπάρχουν οκτώ τύποι επέκτασης, που θα συζητηθούν στις επόμενες ανότητες, με τη σειρά που γίνονται οι επεκτάσεις. 

Μετά από όλες τις επεκτάσεις, αφαιρούνται τα εισαγωγικά.


3.4.2. Επέκταση αγκυλών

Η επέκταση αγκυλών είναι ένας τρόπος δημιουργίας αυθαίρετων συμβολοσειρών. Τα προς επέκταση πρότυπα έχουν τη παρακάτω μορφή: ένα προαιρετικό ΠΡΟΘΕΜΑ (PREAMBLE), μια ακολουθία από συμβολοσειρές, χωρισμένες με κόμμα, που περικλείονται με ένα ζεύγος αγκυλών,  και ένα προαιρετικό ΕΠΙΘΕΜΑ (POSTSCRIPT). Το πρόθεμα προστίθεται στην αρχή κάθε συμβολοσειράς που βρίσκεται μέσα στις αγκύλες, ενώ το επίθεμα προστίθεται στο τέλος. Επέκταση γίνεται από αριστερά προς δεξιά. 

Οι επεκτάσεις αγκυλών μπορεί να είναι ένθετες. Τα αποτελέσματα των επεκτάσεων δεν ταξινομούνται, και διατηρείται η σειρά αριστερά προς δεξιά.

 
franky ~> echo sp{el,il,al}l
spell spill spall

Η επέκταση αγκυλών υλοποιείται πριν από κάθε άλλη επέκταση, και πιθανοί ειδικοί χαρακτήρες διατηρούνται στο αποτέλεσμα. Η επέκταση είναι καθαρά αλφαριθμητική: το Bash δεν αφαρμόζει καμμία συνατκτική ή άλλη διερμηνεία στα συμφραζόμενα της επέκτασης. Για να αποφευχθούν συγκρούσεις με την επέκταση παραμέτρων, η συμβολοσειρά  "${" δεν θεωρείται νόμιμη στην επέκταση αγκυλών.

Μια σωστά διατυπωμένη επέκταση αγκυλών πρέπει να περιέχει δύο εξωτερικές αγκύλες (άνοιγμα και κλείσιμο) χωρίς εισαγωγικά, και τουλάχιστο ένα κόμμα χωρίς εισαγωγικά. Αν δεν είναι σωστά διατυπωμένη η επέκταση αγκυλών παραμένει ως έχει.


3.4.3. Επέκταση περισπωμένης  (tilde)

Αν μια λέξη (σύμβολο) ξεκινά με ένα περισπωμένη (tilde character ~) χωρίς εισαγωγικά, όλοι οι χαρακτήρες μέχρι τη πρώτη κάθετο (slash) εκτός εισαγωγικών (ή όλοι οι χαρακτήρες, αν δεν υπάρχει τέτοια κάθετος) θεωρούνται ως πρόθεμα περισπωμενης (tilde-prefix). Αν κανείς από τους χαρατήκτρες αυτούς δεν είναι σε εισαγωγικά, οι χαρακτήρες του προθέματος αντιμετωπίζονται ως πιθανό όνομα σύνδεσης. Αν το όνομα σύνδεσης είναι κενό αλφαριθμητικό, η περισπωμένη αντικαθίσταται από την τιμή της μεταβλητής φλοιού HOME. Αν η μεταβλητή HOME δεν έχει οριστεί, τότε χρησιμοποιείται ως τιμή αντικατάστασης το όνομα διαδρομής του οικείου καταλόγου του χρήστη που εκτελεί το φλοιό. Αν το όνομα σύνδεσης δεν είναι κενό αλφαριθμητικό τότε η τιμή αντικατάστασης είναι ο οικείος κατάλογος που σχετίζεται με το συγκεκριμένο όνομα σύνδεσης.

Αν το πρόθεμα περισπωμένης είναι "~+", αντικαθίσταται από την τιμή της μεταβλητής φλοιού PWD. Αν το πρόθεμα περισπωμένης είναι "~-", αντικαθίσταται από την τιμή της μεταβλητής φλοιού OLDPWD.

Αν οι χαρακτήρες στο πρόθεμα μετά τη περισπωμένη είναι ένας αριθμός N, προαιρετικά με  "+" ή "-" μπροστά του, το πρόθεμα αντικαθίσταται με το αντίστοιχο στοιχείο από τη στοίβα των καταλόγων, όπως θα εμφανιζόταν αν καλούσαμε την εσωτερική εντολή dirs με τους χαρακτήρες μετά τη περισπωμένη ως όρισμα. Αν δεν υπάρχει "+" ή "-", εννοείεται το "+".

Αν το όνομα σύνδεσης είναι άκυρο ή η επέκταση της περισπωμένης αποτύχει, το σύμβολο παραμένει αμετάβλητο.

Κάθε εκχώρηση μεταβλητής ελέγχεται για προθέματα περισπωμένης χωρίς εισαγωγικά, που ακολουθούν αμέσως μετά από ":" ή "=". Σε αυτές τις περιπτώσεις, επίσης εφαρμόζεται επέκταση περισπωμένης. Συνακόλουθα, μπορούμε να χρησιμοποιήσουμε ονόματα αρχείων με περισπωμένη στους ορισμούς των PATH, MAILPATH, και CDPATH, και ο φλοιός εκχωρεί την εκεταμένη τιμή.

Παράδειγμα:

 
franky ~> export PATH="$PATH:~/testdir"

Το ~/testdir θα επεκταθεί σε $HOME/testdir, έτσι αν το $HOME είναι /var/home/franky, ο κατάλογος /var/home/franky/testdir θα προστεθεί στη τιμή της μεταβλητής PATH.


3.4.4. Επέκταση παραμέτρων και μεταβλητών φλοιού

Ο χαρακτήρας "$" εισάγει επέκταση παραμέτρων, αντικατάσταση εντολών ή αριθμητική επέκταση. Το όνομα της παραμέτρου ή το σύμβολο προς επέκταση μπορεί να περικλείεται σε αγκύλες, που είναι προαιρετικές αλλά προστατεύουν την προς επέκταση μεταβλητή από χαρακτήρες που ακολουθούν αμέσως μετλα και θα μπορούσαν να θεωρηθούν ως τμήμα του ονόματος.

Όταν χρησιμοποιούνται αγκύλες, η αγκύλη κλεισίματος είναι πρώτη  αγκύλη "}" που δεν αναιρείται με backslash, δε βρίσκεται μέσα σε εισαγωγικά, ή σε αριθμητική έκφραση, αντικατάσταση εντολής ή επέκταση παραμέτρων. 

Η βασική μορφή επέκτασης παραμέτρων είναι "${PARAMETER}". Η τιμή του "PARAMETER" αντικαθίσταται. Οι αγκύλες απαιτούνται όταν το "PARAMETER" είναι παράμετρος θέσης με περισσότερα από ένα ψηφία, ή όταν το "PARAMETER" ακολουθείται από ένα χαρακτήρα που δεν πρέπει να ληφθεί ως μέρος του ονόματος. 

Αν ο πρώτος χαρακτήρας στο "PARAMETER" είναι θαυμαστικό, το Bash χρησιμοποιεί την τιμή που αντιστοιχεί στην μεταβλητή με το όνομα που σχηματίζουν οι υπόλοιποι χαρακτήρες του "PARAMETER" Αυτό λέγεται έμμεση επέκταση (indirect expansion).

Σίγουρα γνωρίζετε την απλή επέκταση παραμέτρων (και μεταβλητών) φλοιού αφού συμβαίνει συνέχεθα, ακόμη και στις απλούστερες περιπτώσεις, όπως η ακόλουθη:

 
franky ~> echo $SHELL
/bin/bash

Το παρακάτω είναι παράδειγμα έμμεσης επέκτασης:

 
franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH

Σημειώστε οτι είναι διαφορετικό από το echo $N*.

Η ακόλουθη δομή επιτρέπει τη δημιουργία μεταβλητής ορισμό τιμής:

${VAR:=value}

Παράδειγμα:

 
franky ~> echo $FRANKY
 
franky ~> echo ${FRANKY:=Franky}
Franky

Οι ειδικές παράμετροι, όπως οι  παράμετροι θέσης, δεν μπορούν να οριστούν με αυτό το τρόπο, προφανώς.

Θα συζητήσουμε περισσότερο τη χρήση αγκυλών στην διαχείριση μεταβλητών στο Κεφάλαιο 10. Περισσότερες πληροφορίες στις σελίδες πληροφοριών του Bash.


3.4.5. Αντικατάσταση εντολών

H aντικατάσταση εντολών επιτρέπει την έξοδο μιας εντολής να αντκαταστήσει την ίδια την εντολή. Αυτό συμβαίνει όταν μια εντολή γράφεται ως εξής :

$(command)

ή περικελιεται με βαρείες:

`command`

Το Bash εκτελεί την επέκταση με την εκτέλεση της εντολής και με αντικατάσταση της με την τυπική έξοδό της, αφαιρώντας πιθανές κενές γραμμές. Σε περίπτωση που υπάρχουν ενδιάμεσες σλλαγές γραμμήςς στη έξοδο αφαιρούνται επίσης.

 
franky ~> echo `date`
Thu Feb 6 10:06:20 CET 2003

Όταν χρησιμοποιείται η σύνταξη με τις βαρείες, το backslash διατηρεί την κυριολεκτική του σημασία εκτός αν ακολουθείται από "$", "`", ή "\". Η πρώτη βαρεία που δεν ακολουθεί backslash τερματίζει την αντικατάσταση εντολήε. Όταν χρησιμοποιείται τη μορφή "$(COMMAND)" όλοι οι χαρακτήρες μεταξύ των παρενθέσεων θεωρούνται ως εντολή, χωρίς κανένας χαρακτήρας να έχει ειδική σημασία.

Η αντικατάσταση εντολών μπορεί να είναι ένθετη. Αν η αντικατάσταση βρίσκεται μέσα σε διπλά εισαγωγικά, το αποτέλεσμα δεν υφίσταται τεμαχισμό σε λέξεις και επεκταση ονομάτων.


3.4.6. Αριθμητική επέκταση

Η αριθμητική επέκταση επιτρέπει την εκτίμηση αριθμητικών εκφράσεων και αντικατάσταση του αποτελέσματος. H μορφή της αριθμητικής επέκτασης είναι:

$(( EXPRESSION ))

Η έκφαση αντιμετωπίζεται σαν να είναι μέσα σε διπλά εισγωγικά, αλλά ένα διπλό εισαγωγικό μέσα στην έκφραση δεν αντιμετωπίζεται ιδιαίτερα. Όλα τα σύμβολα της έκφρασης υφίsτανται επέκταση παραμέτρων, αντικατάσταση εντολών και αφαίρεση εισαγωγικών. Η αριθμητική αντικατάσταση μπορεί να είναι ένθετη.

Η εκτίμηση των αριθμητικών εκφράσεων γίνεται με ακεραίους σταθερού πλάτους, χωρίς έλεγχο υπερχείλισης -αν και η διαίρεση με το μηδέν παγιδεύεται  και αναγνωρίζεται ως σφάλμα, Οι τελεστές είναι περίπου οι ίδιοι με την γλώσσα προγραμματισμού C. Σε διάταξη μειούμενης προτεραιότητας, η λίστα έχει ως εξής:

Πίνακας 3-4. Αριθμητικοί τελεστές

Τελεστής  

Σημασία

VAR++ και VAR--

μετα-αύξηση και μετα-μείωση μεταβλητής

++VAR και --VAR

προ-αύξηση και προ-μείωση μεταβλητής

- και +

μοναδιαίο μείον και συν

! και ~

λογική και bitwise άρνηση

**

ύψωση σε δύναμη

*, / και %

πολ/σμός, διαίρεση, ακέραιο υπόλοιπο

+ και -

πρόσθεση, αφαίρεση

<< και >>

αριστερή και δεξιά ολίσθηση

<=, >=, < και >

τελεστές σύγκρισης

== και !=

ισότητα και ανισότητα

&

bitwise AND

^

bitwise ΧOR

|

bitwise OR

&&

λογικό AND

||

λογικό OR

expr ? expr : expr

εκτίμηση υπό συνθήκη

=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^= and |=

εκχωρήσεις

,

διαχωριστικό μεταξύ εκφράσεων

Οι μεταβλητές φλοιού επιτρέπεται να είναι τελεστές. Η επέκταση παραμέτρων γίνεται πριν την εκτίμηση της έκφρασης. Μέσα σε μια έκφραση οι τιμές των μεταβλητών μπορούν να προσπελαστούν χωρίς την χρήση της σύνατξης επέκτασης παραμέτρων. Οι μεταβλητές φλοιού δεν είναι απαραίτητο να είναι δηλωμένες ως ακέραιοι.

Σταθερές που ξεκινούν με 0 (μηδέν) ερμηνεύονται ως οκταδικοί αριθμοί. Αν ξεκινούν με "0x" ή "0X" τότε θεωρούνται δεκαεξαδικοί. Αλλιώς οι αριθμοί παίρνουν τη μορφή  "[BASE'#']N", όπου "BASE" είναι δεκαδικός αριθμός μεταξύ 2 και 64 και παριστά την αριθμητκή βάση, και N είναι ο αριθμός σε αυτή τη βάση. Αν το τμήμα "BASE'#'" παραλείπεται, τότε ως βάση εννοε;iται το 10. Ψηφία μεγαλύτερα του 9 παριστώνται  με πεζά, κεφαλαία γράμματα  και τα σύμβολα, "@", και "_", με τη σειρά που αναφέρονtαι. Αν η βάση είναι μικρότερη ή ίση με 36, τα πεζά και κεφαλαία μπορούν να αναμιχθούν για τη παράσταση αριθμών από το 10 ως το 35.

Οι τελεστές εκτιμώνται με σειρά προτεραιότητας, υπο-εκφράσεις σε παρενθέσεις εκτιμώνται πρώτες και υπερβαίνουν τους κανόνες προτεραιότηατς.

Όταν είναι δυνατό οι χρήστες του Bash καλό είναι να χρησιμοποιούν τη σύνταξη με τις ορθογώνιες παρενθέσεις:

$[ EXPRESSION ]

Όμως αυτό απλά υπολογίζει την έκφραση EXPRESSION, και δεν κάνει ελέγχους:

 
franky ~> echo $[365*24]
8760

Δείτε την Ενότητα 7.1.2.2, μεταξύ άλλων, για πρακτικά παραδείγματα με σενάρια.


3.4.7. Αντικατάσταση διεργασιών

Η αντικατάσταση διεργασιών χρησιμοποιείται σε συστήματα που υποστηρίζουν ονομασμένες σωληνώσιες (FIFOs) ή τη μέθοδο  /dev/fd για την ονομασία ανοικτών αρχείων. Έχει τη μορφή

<(LIST)

ή

>(LIST)

Η λίστα των διεργασιών εκτελείται με την είσοδο ή έξοδο συνδεδεμένη σε μια σωλήνωση FIFO ή σε κάποιο αρχείο στο /dev/fd. Το όνομα αυτού του αρχείου περνάει ως όρισμα στη τρέχουσα εντολή ως αποτέλεσμα της επέκτασης. Αν χρησιμοποιηθεί η μορφή ">(LIST)" τότε το αρχείο αποτελεί είσοδο για τη λίστα , αλλιώς αποτελεί την έξοδο. Σημιώστα οτι δεν επιτρέπονται κενά μεταξύ των συμβόλων < και > και της αριστερής παένθεσης, αλλιώς η δομή ερμηνεύεται ως ανακατεύθυνση.

Όταν διατίθεται, η αντικατάσταση διεργασιών γίνεται ατυτόχρονα με τις άλλες επεκτάσεις και αντικαταστάσεις.

Περισσότερες πληροφορίες στην Ενότητα 8.2.3.


3.4.8. Χωρισμός λέξεων

Ο φλοιός σαρώνει το αποτέλεσμα των επεκτάσων και αντικαταστάσεων που δεν βρίσκονται μέσα σε διπλά εισαγωγικά για χωρισμό λέξεων.

Κάθε χαρακτήρας στο $IFS θεωρείται ως οριοθέτης, και ο φλοιός χωρίζει το εποτέλεσμα σε λέξεις με βάση αυτούς τους οριοθέτες. Αν η μεταβλητή IFS δεν είναι ορισμένη, ή η τιμή της είναι το προκαθορισμένο "'<space><tab><newline>'", τότε οποιαδήποτε ακολουθία από αυτούς τους χαρακτήρες θεωρείατι οτι οριοθετεί μια λέξη. Αν η μεταβλητή IFS έχει τιμή null τότε δεν γίνεται κανένας χωρισμόας. Αν η μεταβλητή IFS έχει άλλη τιμή τότε η οριοθέτηση γίνεται με συνδυασμό των χαρακτήρων οριοθέτησης και των συνηθισμένων 'λευκών' χαρακτήρων.

Ορίσματα που είναι ρητά κενά  ("""" or "''") διατηρούνται. Κενά ορίσματα χωρίς εισαγωγικά που προκύπτουν από την επεέκταση παραμέτρων χωρίς τιμή, παραλείπονται.

Note

Επεκτάσεις και χωρισμός λέξεων

Αν δεν γίνουν επεκτάσεις τότε δεν γίνεται και χωρισμός λέξεων.


3.4.9. Επέκταση ονομάτων αρχείων

Μετά το χωρισμό λέξεων, και αν δεν έχει τεθεί η επιλογή -f (δείτε Ενότητα 2.3.2), το Bash σαρώνει κάθε λέξη για χαρακτήρες "*", "?", και "[". Αν βρεθεί τέτοιος χαρακτήρας, η λέξη θεωρείται ΠΡΟΤΥΠΟ (PATTERN), και αντικαθίσταται με αλφαβητικά ταξινομημένη λίστα ονομάτων αρχείων που ταιριάζουν. Αν δεν υπάρχουν ονόματα αρχείων που ταυτίζονται, και η επιλογή φλοιού nullglob είναι απενεργοποιημένη, η λέξη μένει αμετάβλητη. Αν η επιλογή nullglob είναι ορισμένη, και δεν υπάρχουν ταυτίσεις, η λέξη αφαιρείται. Αν ενεργοποιηθεί η επιλογή φλοιού nocaseglob, η ταύτιση γίνεται χωρίς δι'ακριση πεζών ή κεφαλαίων χαρακτήρων.

Όταν ένα πρότυπο χρησιμοποιείται για δημιουργία ονομάτων αρχείων, ο χαρακτήρας "." στην αρχή ενός ονόματος αρχείου ή αμέσως μετά μια κάθετο πρέπει να ταυτίζεται ρητά, εκτός να έχει τεθεί η επιλογή  dotglob. Κατά τη ταύτιση ονομάτων αρχείων, ο χαρακτήρας της καθέτου  πάντα ταυτίζεται ρητά. Στις άλλες περιπτώσεις ο χαρακτήρας "." δεν αντιμετωπίζεται ιδιαίτερα.

Η μεταβλητή φλοιού GLOBIGNORE μπορεί να χρησιμοποιηθεί για τον περιορισμό τοτ συνόλου των ονομάτων που ταυτίζονται με ένα πρότυπο. Αν η GLOBIGNORE έχει οριστεί, κάθε όνομα αρχέιου που ταιριάζει στη ταύτιση αλλά ταιριάζει και με κάποιο πρότυπο της GLOBIGNORE αφαιρείται από τη λίστα των ατυτίσεων. Τα ονόματα αρχείων . και .. αγνοούνται πάντα, ακόμη αι αν η GLOBIGNORE έχει οριστεί. Όμως, ο ορισμός της GLOBIGNORE έχει ως παρεπόμενο την ενεργοποίηση της επιλογής φλοιού dotglob, έτσι ώστε όλα τα ονόματα που αρχίζουν με "." θα ταυτιστούν. Για να έχετε τη προηγούμενη συμπεριφορά αγνόησης των ονομάτων αρχείων που ξεκινούν με ".", πρέπει να βάλετε το ".*" στα πρότυπα της GLOBIGNORE. Η επιλογή dotglob είναι ανενεργή όταν η GLOBIGNORE δεν είναι ορισμένη.


3.5. Ψευδώνυμα

3.5.1. Τι είναι τα ψευδώνυμα;

Ένα ψευδώνυμο επιτρέπει ένα αλφαριθμητικό να αντικαθιστά μια λέξη όταν αυτή είναι η πρώτη λέξη μας απλής εντολής. Ο φλοιός διατηρεί μια λίστα ψευδωνύμων που μπορεί να τροποποιηθεί με τις εσωτερικές εντολές alias και unalias. Η εντολή alias χωρίς επιλογές εμφανίζει τη λίστα των ψευδωνύμων που είναι γνωστά στον τρέχοντα φλοιό.

 
franky: ~> alias
alias ..='cd ..'
alias ...='cd ../..'
alias ....='cd ../../..'
alias PAGER='less -r'
alias Txterm='export TERM=xterm'
alias XARGS='xargs -r'
alias cdrecord='cdrecord -dev 0,0,0 -speed=8'
alias e='vi'
alias egrep='grep -E'
alias ewformat='fdformat -n /dev/fd0u1743; ewfsck'
alias fgrep='grep -F'
alias ftp='ncftp -d15'
alias h='history 10'
alias fformat='fdformat /dev/fd0H1440'
alias j='jobs -l'
alias ksane='setterm -reset'
alias ls='ls -F --color=auto'
alias m='less'
alias md='mkdir'
alias od='od -Ax -ta -txC'
alias p='pstree -p'
alias ping='ping -vc1'
alias sb='ssh blubber'
alias sl='ls'
alias ss='ssh octarine'
alias sss='ssh -C server1.us.xalasys.com'
alias sssu='ssh -C -l root server1.us.xalasys.com'
alias tar='gtar'
alias tmp='cd /tmp'
alias unaliasall='unalias -a'
alias vi='eval `resize`;vi'
alias vt100='export TERM=vt100'
alias which='type'
alias xt='xterm -bg black -fg white &'
 
franky ~>

Τα ψευδώνυμα είναι χρήσιμα για τον ορισμό προεπιλεγμένων μορφών σε εντολές που διατίθενται σε πολλές εκδόσεις ή για τον ορισμό των προκαθορισμένων επιλογών σε μια εντολή. Μια άλλη επιλογή είναι η παράβλεψη συνηθισμένων αναγραμματσμών στη πληκτρολόγηση.

Η πρώτη λέξη σε κάθε απλή εντολή, αν δεν έχει εισγωγικά, ελέγχεται για ψευδώνυμα. Αν είναι τέτοιο, τότε αντικαθίσταται. Το ψευδώνυμο και το κείμενο αντικατάστασης μπορεί να περιέχει οποιαδήποτε νόμιμη είσοδο φλοιού, συμπεριλαμβανομένων και μεταχαρακτήρων φλοιού, με την εσξίρεση οτι ένα ψευδώνυμο δεν μπορεί να περιέχει "=". Η πρώτη λέξη του κειμένου αντικατάστασης ελέγχεται για ψευδώνυμα, με εξαίρεση τον εαυτό της. Αυτό σημαίνει οτι μπορούμε να αντιστοιχίσουμε το ls στο ls -F, λόγου χάρη, και το Bash δεν θα προχωρήσει σε αναδρομική αντικατάσατση του ψευδωνύμου. Αν ο τεέυταίος χαρακτήρας του ψευδωνύμου είναι κενό ή tab, τότε η επόμενη λέξη στη γραμμή εντολών ελέγχεται για ψευδώνυμα.

Τα ψευδώνυμα δεν επεκτείνονται όταν ο φλοιός δεν είναι διαλογικός, εκός και αν έχει ενεργοποιηθεί η ειλογή expand_aliases μέσω της ενσωματωμένης εντολής shopt.


3.5.2. Δημιουργία και διαγραφή ψευδωνύμων

Τα ψευδώνυμα δημιουργούνται με την εσωτερική εντολή alias. Για μόνιμη χρήση εισάγετε τα ψευδώνυμα σε ένα από τα αρχεία ρύθμισης του φλοιού. Αν εισάγετε ένα ψευδώνυμο στη γραμμή εντολών τότε αυτό είνα γνωστό μόνο στο τρέχοντα φλοιό..

 
franky ~> alias dh='df -h'
 
franky ~> dh
Filesystem            Size  Used Avail Use% Mounted on
/dev/hda7             1.3G  272M 1018M  22% /
/dev/hda1             121M  9.4M  105M   9% /boot
/dev/hda2             13G  8.7G  3.7G  70% /home
/dev/hda3             13G  5.3G  7.1G  43% /opt
none                  243M     0  243M   0% /dev/shm
/dev/hda6             3.9G  3.2G  572M  85% /usr
/dev/hda5             5.2G  4.3G  725M  86% /var
 
franky ~> unalias dh
 
franky ~> dh
bash: dh: command not found
 
franky ~>

Το Bash πάντα διαβάζει τουλάχιστο μια πλήρη γραμμή εισόδου πριν την εκτέλεση οποιασδήποτε εντολής της γραμμής. Τα ψευδώνυμα επεκτείνονται όταν διαβάζεται μια γραμμή εντολών, όχι όταν εκτελείται. Γι΄αυτό το λόγο ένας ορισμός ψευδωνύμου στην ίδια γραμμή με η χρήση του δεν μπορεί να λειτουργήσει. Αυτή η συμπεριφορά ισχύει και για την εκτέλεση συναρτήσεων. Τα ψευδώνυμα επεκτείνονται κατά την ανάγνωση του ορισμούκαι όχι κατά την εκτέλεση της συνάρτησης, επειδή ο ορισμός της συνάρτησης είναι μια σύνθετη εντολή. Ως συνέπεια, ψεδυδώνυμα που ορίζονται σε μια συνάρτηση δεν είναι διαθέσιμα παρά μόνο μετά την εκτέλεση της συνάρτησης. Για να είμαστε ασφαλείς, πάντα δηλώνουμε τα ψευδώνυμα σε ξεχωριστές γραμμές, και δεν χρησιμοποιούμε την εντολή alias σε σύνθετες εντολές.

Τα ψευδύνυμα δεν κληρονομούνται σε θυγατρικές διεργασίες. Ο φλοιός Bourne (sh) δεν αναγνωρίζει ψευδώνυμα.

Περισσότερα για τις συναρτήσεις στο Κεφάλαιο 11.

Tip

Οι συναρτήσεις είναι ταχύτερες

Τα ψευδώνυμα αναλύονται μετά τις συναρτήσεις και γι' αυτό υπάρχει μεγαλύτερη καθυστέρηση. Αν και τα ψευδώνυμα είναι ευκολότερα στη κατανόηση, οι συναρτήσεις φλοιού προτιμώνται  σχεδόν σε κάθε περιπτωση.


3.6. Άλλες επιλογές του Bash

3.6.1. Εμφάνιση επιλογών

Ήδη έχουμε συζητήσει μερικές επιλογές του Bash που είναι χρήσιμες για την εκσφαλμάτωση σεναρίων. Σε αυτή την ενότητα, θα δούμε σε μεγαλύτερο βάθος στις επιλογές του Bash.

Με την επιλογή -o στην εντολή set εμφανίζονται όλες οι επιλογές:

 
willy:~> set -o
allexport              off
braceexpand            on
emacs                  on
errexit                off
hashall                on
histexpand             on
history                on
ignoreeof              off
interactive-comments   on
keyword                off
monitor                on
noclobber              off
noexec                 off
noglob                 off
nolog                  off
notify                 off
nounset                off
onecmd                 off
physical               off
posix                  off
privileged             off
verbose                off
vi                     off
xtrace                 off

Δείτε στις σελίδες πληροφόρησης του Bash, Shell Built-in Commands->The Set Built-in fγια μια περιγραφή κάθε επιλογής. Πολλές επιλογές έχουν συντομέυσεις ενός χαρακτήρα: για παράδειγμα, η επιλογή xtrace είναι ισοδύναμη με την set -x.


3.6.2. Τροποποίηση επιλογών

Οι επιλογές φλοιού μπορούν να ρυθμιστούν διαφορετικά από τη προεπιλογή είτε κατά τη κλήση του φλοιού, ή κατά την εκτέλεσή του. Αυτές οι τροποποιήσεις μπορούν να περιληφθούν στα αρχεία ρύθμισης του φλοιού.

Η ακόλουθη εντολή εκτελεί ένα σενάριο σε κατάσταση συμβατή με POSIX.

 
willy:~/scripts> bash --posix script.sh

Για προσωρινή αλλαγή, ή για χρήση σε ένα σενάριο, καλύτερα να χρησιμοποιήσουμε την εντολή set. Χρησιμοποιούμε - (μείον) για ενεργοποίηση επιλογής + για απανεργοποίηση.

 
willy:~/test> set -o noclobber
 
willy:~/test> touch test
 
willy:~/test> date > test
bash: test: cannot overwrite existing file
 
willy:~/test> set +o noclobber
 
willy:~/test> date > test

Το παραπάνω παράδειγμα επιδεικνύει την επιλογή noclobber, που αποτρέπει την τροποποίηση υπαρχόντων αρχείων από τις λειτουργίες ανακατεύθυνσης. Το ίδιο συμβαίνει με επιλογές ενός χαρακτήρα, λόγου χάρη το -u, που χειρίζεται τις μη ορισμένες μεταβλητές σαν σφάλμα, και τερματίζει έναν μη-διαλογικό φλοιό μόλις συναντήσει τέτοιο σφάλμα.

 
willy:~> echo $VAR
 
 
willy:~> set -u
 
willy:~> echo $VAR
bash: VAR: unbound variable

Αυτή η επιλογή είναι επίσης χρήσιμη για την ανίχνευση λανθασμένων εκχωρλησεων σε μεταβλητές: το ίδιο σφάλμα θα προκληθεί, λόγου χάρη, όταν εκχωρείται ένα αλφαριθμητικό σε μια μεταβλητή που έχει δηλωθεί ως ακέραια.

Ένα τελευταίο παράδειγμα, δείχνει την χρήση της επιλογής noglob, που αποτρέπει την επέκταση των ειδκών χαρακτήρων.

 
willy:~/testdir> set -o noglob
 
willy:~/testdir> touch *
 
willy:~/testdir> ls -l *
-rw-rw-r--    1 willy    willy        0 Feb 27 13:37 *

3.7. Περίληψη

Το περιβάλλον του Bash μπορεί να διαμορφωθεί είτε καθολικά ή ανά χρήστη. Για τη διαμόρφωση χρησιμοποιούνται διάφορα αρχεία ρυθμίσεων.

Τα αρχεία αυτά περιέχουν επιλογές φλοιού, ορισμούς μεταβλητών, ορισμούς συναρτήσεων και διάφορα άλλα δομικά στοιχεία που μας επιτρέπουν να δημιουργήσουμε το περιβάλλον που μας βολεύει.

Εκτός από τις δεσμευμένες λέξεις του των φλοιών Βourne και Bash, τα ονόματα μεταβλητών μπορούν αν επιλεγούν ελεύθερα.

Επειδή πολλοί χαρακτήρες έχουν διπλή ή και τριπλή σημασία,ανάλογα με το περιβάλλον, το Bash χρησιμοποιεί ένα σύστημα εισαγωγικών που αφαιρεί την ειδική σημασία από έναν ή πολλαπλούς χαρακτήρες, όταν δεν απαιτείται ειδκός χειρισμός.

Το Bash, για να καθορίσει ποιές εντολές θα εκτελέσεθ, χρησιμοποιεί διάφορες μεθόδους επέκτασης των λέξεων (συμβόλων) της γραμμής εντολών.


3.8. Ασκήσεις

Γι' αυτή την άσκηση, θα χρειαστεί να διβάσετε τις σελίδες του εγχειριδίου (man) του useradd, γιατί θα χρησιμοποιήσουμε τον κατάλογο /etc/skel για να αποθηκεύσουμε τα προεπιλεγμένα αρχεία ρυθμίσεων, που αντιγράφονται στον οικείο κατάλογο κάθε νέου χρήστη.

Πρώτα θα εκτελέσουμε μερικές ασκήσεις ορισμού και εμφάνισης μεταβλητών.

1.      Δημιουργείστε 3 μεταβλητές, VAR1, VAR2 και VAR3. Αρχικοποιείστε τις με τιμές "thirteen", "13" και  "Happy Birthday" αντίστοιχα.

2.      Εμφανίστε τις τιμές των μεταβλητών.

3.      Είναι τοπικές ή καθολικές μεταβλητές;

4.      Διαγράψτε την VAR3.

5.      Μπορείτε να δείτε τις δύο απομένουσες μεταβλητές σε νέο παράθυρο τερματικού;

6.      Τροποποιείστε το αρχείο /etc/profile έτσι ώστε όλοι οι χρήστες να καλωσορίζονται κατά την σύνδεση (ελέγξτε το).

7.      Για τον λογαριασμό root, ορίστε τη προτροπή σε κάτι σαν "Danger!! root is doing stuff in \w", κατά προτίμηση σε ένα έντονο χρώμα όπως κόκκινο ή σε reverse video.

8.      Βεβαιωθείτε οτι οι νέοι χρήστες λαμβάνουν μια προσωποποιημένη προτροπή που τους πληροφορεί σε ποιό σύστημα και ποιό κατάλογο βρίσκονται. Ελέγξτε τις αλλαγές σας προσθέτοντας ένα νέο όνομα χρήστη και συνδεθείτε με αυτό..

9.      Γράψτε ένα σενάριο όπου δίνετε δύο ακέραιες τιμές σε δύο μεταβλητές. Το σενάριο πρέπει να υπολογίζει το εμβαδό ενός ορθογωνίου. Πρέπει να συνοδεύεται από σχόλια και να εμφανίζει όμορφα το αποτέλεσμα.

Μη ξεχάσετε να αλλάζετε τα δικαιώματα στα σενάρια με chmod !


Κεφάλαιο 4. Κανονικές εκφράσεις

Σε αυτό το κεφάλαιο θα συζητήσουμε:

·         Τη χρήση κανονικών εκφράσεων

·         Τους μεταχαρακτήρες κανονικών εκφράσεων

·         Την εύρεση προτύπων σε αρχεία ή έξοδο

·         Τις κλάσεις χαρακτήρων και το εύρος τους στο Bash


4.1. Κανονικές εκφράσεις

4.1.1. Τι είναι οι κανονικές εκφράσεις;

Μια  κανονική έκφραση είναι ένα πρότυπο που περιγράφει ένα σύνολο αλφαριθμητικών (συμβολοσειρών). Οι κανονικές εκφράσεις δομούνται κατ'αναλογία με τις αριθμητικές εκφράσεις, χρησιμοποιώντας διάφορους τελεστές για το συνδυασμό μικρότερων εκφράσεων.

Τα στοιχειώδη δομικά στοιχεία είναι κανονικές εκφράσεις που ταυτίζονται με απλούς χαρακτήρες.Οι περισσότεροι χαρακτήρες, όλα τα γράμματα και τα ψηφία, είναι κανονικές εκφράσεις που ταυτίζονται με το ευατό τους, Οι χαρακτήρες με ειδική σημασία, μπορούν να ακυρωθούν αν προηγείται ένα backslash.


4.1.2. Μεταχαρακτήρες κανονικών εκφράσεων

Μια κανονική έκφραση μπορεί να ακολουθείται από κάποιο τελεστή επανάληψης (μεταχαρακτήρα):

Πίνακς 4-1. Τελεστές κανονικών εκφράσεων

Τελεστής 

Αποτέλεσμα

.

Ταυτίζεται με οποιοδήποτε μεμονωμένο χαρακτήρα.

?

Ο χαρακτήρας που προηγείται είναι προαιρετικός και θα ταυτιστεί το πολύ μία φορά.

*

Ο χαρακτήρας που προηγείται θα ταυτιστεί μηδέν ή περισσότερες φορές.

+

Ο χαρακτήρας που προηγείται θα ταυτιστεί μία ή περισσότερες φορές.

{N}

Ο χαρακτήρας που προηγείται θα ταυτιστεί ακριβώς Ν φορές.

{N,}

Ο χαρακτήρας που προηγείται θα ταυτιστεί Ν ή περισσότερες φορές.

{N,M}

Ο χαρακτήρας που προηγείται θα ταυτιστεί Ν ή περισσότερες φορές, αλλά όχι περισσότερες από Μ.

-

Παριστά το εύρος αν δεν είναι πρώτος ή τελευταίος αρακτήρας, ή τελευταίος χαρακτήρας σε λίστα.

^

Ταυτίζει την αρχή μιας γραμμής. Επίσης παριστά τους χαρακτήρες που δεν περιέχονται σε μια λίστα.

$

Ταυτίζει το τέλος μιας γραμμής.

\b

Ταυτίζει το τέλος μιας λέξης.

\B

Ταυτίζει άδεια συμβολοσειρά που δεν είναι τέλος λέξης.

\<

Ταυτίζει άδεια συμβολοσειρά στην αρχή μιας λέξης.

\>

Ταυτίζει άδεια συμβολοσειρά στο τέλος μιας λέξης..

Δύο κανονικές εκφράσεις μπορεί να συνενωθούν. Η κανονική έκφραση που προκύπτει ταυτίζεται με οποιαδήποτε συμβολοσειρά προκύπτει από τη συνένωνη δύο έγκυρων συμβολοσειρών που αντίστοιχα ταυτίζονται με τις επιμέρους συμβολοσειρές.

Δυο κανονικε εκφράσεις μπορεί να συνδυαστούν με τον τελεστή εναλλαγής "|". Η νέα κανονική έκφραση ταυτίζεται με οποιαδήποτε από τις υπιο-εκφράσεις.

Η επανάληψη προηγείται της συνένωσης, που με τη σειρά της προηγείται της εναλλαγής. Η χρήση παρενθέσεων αλλάξει τους κανόνες προτεραιότητας. 


4.1.3. Βασικές και εκτεταμένες κανονικές εκφράσεις

Στις βασικές κανονικές εκφράσεις οι μεταχαρακτήρες "?", "+", "{", "}", "|", "(", και ")" δεν έχουν ειδική σημασία. Πρέπει να χρησιμοποιηθούν οι "\?", "\+", "\{", "\}, "\|", "\(", and "\)".

Ελέγξτε τη τεκμηρίωση του συστήματός σας για να δείτε αν οι εντολές σας χρησιμοποιούν βασικές και εκταταμένες κανονικές εκφράσεις.


4.2. Παραδείγματα με το grep

4.2.1. Τι είναι το grep?

Η εντολή grep αναζητά σε αρχεία κειμένου γραμμές που περιέχουν ένα πρότυπο. Όταν βρίσκει μια ταύτιση, αντιγράφει τη συκεκριμένη γραμμή στη πρότυπη έξοδο (ως προεπιλογή) ή σε όποια άλλη άξοδο ορίζουν οι επιλογές της εντολής.

Αν και η grep υποθέτει ταύτιση σε κείμενο, δεν έχει συγκεκριμένο όριο στο μέγεθος γραμμής, πέρα από τη διαθέσιμη μνήμη, και μπορεί να ταυτίσει πρότυπα οποιουδήποτε μεγέθους.Αν το τελικό byte της γραμμής εισόδου δεν είναι newline, η grep σιωπηρά προσθέτει ένα. Αφού η αλλαγή γραμμής είναι διαχωριστικό προτύπων και γραμμών, δεν υπάρχει τρόπος να ταυτίσουμε χαρακτήρες αλλαγής γραμμής..

Μερικά παραδείγματα:

 
cathy ~> grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
 
cathy ~> grep -n root /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
12:operator:x:11:0:operator:/root:/sbin/nologin
 
cathy ~> grep -v bash /etc/passwd | grep -v nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
news:x:9:13:news:/var/spool/news:
mailnull:x:47:47::/var/spool/mqueue:/dev/null
xfs:x:43:43:X Font Server:/etc/X11/fs:/bin/false
rpc:x:32:32:Portmapper RPC user:/:/bin/false
nscd:x:28:28:NSCD Daemon:/:/bin/false
named:x:25:25:Named:/var/named:/bin/false
squid:x:23:23::/var/spool/squid:/dev/null
ldap:x:55:55:LDAP User:/var/lib/ldap:/bin/false
apache:x:48:48:Apache:/var/www:/bin/false
 
cathy ~> grep -c false /etc/passwd
7
 
cathy ~> grep -i ps ~/.bash* | grep -v history
/home/cathy/.bashrc:PS1="\[\033[1;44m\]$USER is in \w\[\033[0m\] "
 

Με τη πρώτη εντολή, η χρήστης cathy εμφανίζει τις γραμμές του αρχείου /etc/passwd που περιέχουν τη συμβολοσειρά root.

Μετά εμφανίζει τις γραμμές με αριθμό γραμμής μπροστά.

Με τη τρίτη εντολή ελέγχει ποιοί χρήστες δεν χρησιμοποιούν bash, αλλά οι λογαριασμοί με φλοιό nologin δεν εμφανίζονται..

Κατόπιν μετρά τους λογαριασμούς που έχουν ως φλοιό το /bin/false.

Η τελευταία εντολή εμφανίζει τις γραμμές όλων των αρχείων του οικείου καταλόγου της που ξεκινούν με ~/.bash, εξαιρούμενης τη ταύτισης με το πρότυπο history, ώστε να εξαιρεθούν οι ταυτίσεις από το αρχείο ~/.bash_history που μπορεί να περιέχουν το ίδιο πρότυπο, με πεζά ή κεφαλαία γράμματα. Σημειώστε οτι αναζητούμε τη συμβολοσειρά "ps", και όχι την εντολή  ps.

Τώρα ας δούμε τι μπορούμε να κάνουμε με τη grep, με τη χρήση κανονικών εκφράσεων.


4.2.2. Grep και κανονικές εκφράσεις

Note

Αν δεν βρίσκεστε σε Linux

 

Σε αυτά τα παραδείγματα χρησιμοποιούμε τη GNU grep, η οποία υποστηρίζει εκτεταμένες κανονικές εκφράσεις. H GNU grep είναι η προεπιλογή στα συστήματα Linux. Αν εργάζεστε σε άλλου τύπου σύστημα Unix, ελέγξτε την έκδοση που χρησιμοποιείτε με την επιλογή  -V. Η GNU grep μπορεί να μεταφορτωθεί από τον ιστοτόπο http://gnu.org/directory/.


4.2.2.1. Άγκυρες γραμμών και λέξεων 

Από το προηγούμενο παράδειγμα, τώρα θέλουμε να εμφανίσουμε αποκλειστικά τισ γραμμές που αρχίζουν με "root":

 
cathy ~> grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash

Αν θέλουμε να δούμε ποιοί λογαριασμοί δε διαθέτουν κάποιο φλοιό, αναζητούμε τις γραμμές που τελειώνουν με ":":

 
cathy ~> grep :$ /etc/passwd
news:x:9:13:news:/var/spool/news:

Για να ελέγξουμε αν η μεταβλητή PATH εξήχθη στο αρχείο ~/.bashrc, πρώτα επιλέγουμε τις γραμμές με "export" και μετά αναζητούμε τη συμβολοσειρά "PATH", ως αρχή λέξης, έτσι ώστε να μην εμφανιστούν διαδομές όπως η MANPATH και άλλες:

 
cathy ~> grep export ~/.bashrc | grep '\<PATH'
  export PATH="/bin:/usr/lib/mh:/lib:/usr/bin:/usr/local/bin:/usr/ucb:/usr/dbin:$PATH"

Παρόμοια, το \> ταυτίζει συμβολοσειρά με το τέλος λέξης.

Αν θέλετε να βρείτε μια συμβολοσειρά που αποτελεί ξαχωριστή λέξη (μεταξύ κενών), είναι καλύτερα να χρησιμοπιήσετε την επιλογή -w, όπως σε αυτό το παράδειγμα όπου εμφανίζουμε πληροφορίες για το διαμέρισμα root:

 
cathy ~> grep -w / /etc/fstab
LABEL=/                 /                       ext3    defaults        1 1

Άν δεν χρησιμοποιηθεί αυτή η επιλογή, θα εμφανιστούν όλες οι γραμμές του συστήματος αρχείων..


4.2.2.2. Κλάσεις χαρακτήρων

Μια  έκφραση ορθογώνιων παρενθέσεων είναι μια λίστα χαρακτήρων που περικλείονται σε "[" και "]". Ταυτίζει κάθε απλό χαρακτήρα της λίστας. Αν ο πρώτος χαρακτήρας σε αυτή τη λίστα είναι το "^", τότε ταυτίζει κάθε χαρακτήρα ΔΕΝ είναι στη λίστα. Για παράδειγμα, η κανονική έκφραση "[0123456789]" ταυτίζει κάθε απλό ψηφίο..

Μέσα σε μια έκφραση ορθογώνιων παρενθέσεων, μια έκφραση εύρους αποτελείται από δύο χαρακτήρες που χωρίζονται με "-". Ταυτίζει κάθε χαρακτήρα που βρίσκεται μεταξύ των δύο χαρακτήρων , συμπεριλαμβανομένων των άκρων. Χρησιμοποιείται η τοπική κωδικοποίηση χαρακτήρων. Για παράδειγμα, στη προεπιλεγμένη κωδικοποίηση της  C, η έκφραση "[a-d]" ισοδυναμεί με την "[abcd]". Πολλές τοπικές κωδικοποιήσεις ταξινομούν τους χαρακτήρες με λεξικογραφική σειρά, και σε αυτές τις κωδικοποιήσεις η έκφραση "[a-d]" μπορεί να ισοδυναμεί με  την "[aBbCcDd]", για παράδειγμα. Για να διασφαλίσουμε την παραδοσιακή διερμηνεία των εκφράσεων, μπορούμε να χρησιμοποιήσουμε τη κωδικοποίηση της C θέτοντας τις μεταβλητές περιβάλλοντος LC_COLLATE ή LC_ALL στην τιμή "C".

Τελικά, μερικές ονομασμένες κλάσεις χαρακτήρων είναι γνωστές στις εκφράσεις ορθογώνιων παρενθέσεων. Δείτε τις σελίδες εγχειριδίου ή πληροφοριών της εντολής grep σχετικά με τις προκαθορισμένες κλάσεις χαρακτήρων.

 
cathy ~> grep [yf] /etc/group
sys:x:3:root,bin,adm
tty:x:5:
mail:x:12:mail,postfix
ftp:x:50:
nobody:x:99:
floppy:x:19:
xfs:x:43:
nfsnobody:x:65534:
postfix:x:89:
 
cathy ~> ls *[1-9].xml
app1.xml  chap1.xml  chap2.xml  chap3.xml  chap4.xml

Στο παράδειγμα, πρώτα εμφανίζονται όλες οι γραμμές που περιέχουν "y" ή "f". Κατόπιν υπάρχει ένα παράδειγμα χρησης του έυρους χαρακτήρων με την εντολή  ls.


4.2.2.3. Μπαλαντέρ

Χρησιμοποιούμε το "." για τη ταύτιση οποιυδήποτε απλού χαρακτήρα. Αν θέλετε να εμφανίσετε μια λίστα όλων των Αγγλικών λέξεων πέντε χαρακτήρων που ξεκινούν με "c" και τελιώνουν με "h" (καλό για σταυρόλεξα) τότε:

 
cathy ~> grep '\<c...h\>' /usr/share/dict/words
catch
clash
cloth
coach
couch
cough
crash
crush

Αν θέλετα να εμφανίσετε γραμμές που περιέχουν την τελεία (κυριολεκτικά) χρησιμοποιείστε την επιλογή -F της grep.

Για τη ταύτιση πολλών χαρακτήρων, χρησιμοποιούμε τον αστερίσκο. Αυτό το παράδειγμα επιλέγει όλες τις λέξεις που αρχίζουν με "c" και τελειώνουν με "h" από το λεξικό του συστήματος:

 
cathy ~> grep '\<c.*h\>' /usr/share/dict/words
caliph
cash
catch
cheesecloth
cheetah
--output omitted--

Αν θέλετε να βρείτε τον αστερίσκο (κυριολεκτικά) σε ένα αρχείο ή έξοδο, χρησιμοποιείστε τη grep -F:

 
cathy ~> grep * /etc/profile
 
cathy ~> grep -F '*' /etc/profile
for i in /etc/profile.d/*.sh ; do

4.3. Ταύτιση προτύπων με το Bash

4.3.1. Διαστήματα χαρακτήρων

Εκτός απί τη grep και τις κανονικές εκφράσεις, υπάρχουν αρκετές δυνατότητες ταύτισης προτύπων στον ίδιο το φλοιό, χωρίς να απαιτείται η χρήση εξωτερικού προγράμματος.

´Οπως ήδη γνωρίζετε, ο αστερίσκος (*) και το ερωτηματικό (?) ταυτίζουν οποιαδήποτε συμβολοσειρά και οποιοδήποτε χαρακτήρα, αντίστοιχα. Για κυριολεκτική ταύτιση, αυτοί οι χαρακτήρες πρέπει να περιβληθούν με διπλά εισαγωγικά:

 
cathy ~> touch "*"
 
cathy ~> ls "*"
*

Όμως μπορείτε να χρησιμοποιήσετε ορθογώνιες παρενθέσεις για τη ταύτιση καθενός από τους περικλειόμενους χαρακτήρες ή για ταύτιση σε κάποιο εύρος χαρακτήρων, όταν έχουμε ζεύγη χαρακτήρων χωρισμένα με "-". Ένα παράδειγμα::

 
cathy ~> ls -ld [a-cx-z]*
drwxr-xr-x    2 cathy    cathy          4096 Jul 20  2002 app-defaults/
drwxrwxr-x    4 cathy    cathy          4096 May 25  2002 arabic/
drwxrwxr-x    2 cathy    cathy          4096 Mar  4 18:30 bin/
drwxr-xr-x    7 cathy    cathy          4096 Sep  2  2001 crossover/
drwxrwxr-x    3 cathy    cathy          4096 Mar 22  2002 xml/

Αυτή η εντολή εμφανίζει τα αρχεία του οικείου καταλόγου της cathy που ξεκινούν με "a", "b", "c", "x", "y" ή "z".

Αν ο πρώτος χαρακτήρας μέσα στις ορθογώνιες παρενθέσεις είναι "!" ή "^", τότε ταυτίζονται οι χαρακτήρες που δεν περιλαμβάνονται. Για να ταυτίσουμε το μείον ("-"), μπορούμε να τη περιλάβουμε ως πρώτο ή τελευταίο χαρακτήρα του συνόλου. Για τον υπολογισμό του εύρους χρησιμοποιείται η τοπική κωδικοποίηση χαρακτήρων. Για παράδειγμα, στη προεπιλεγμένη κωδικοποίηση της  C, η έκφραση "[a-d]" ισοδυναμεί με την "[abcd]". Πολλές τοπικές κωδικοποιήσεις ταξινομούν τους χαρακτήρες με λεξικογραφική σειρά, και σε αυτές τις κωδικοποιήσεις η έκφραση "[a-d]" μπορεί να ισοδυναμεί με  την "[aBbCcDd]", για παράδειγμα. Για να διασφαλίσουμε την παραδοσιακή διερμηνεία των εκφράσεων, μπορούμε να χρησιμοποιήσουμε τη κωδικοποίηση της C θέτοντας τις μεταβλητές περιβάλλοντος LC_COLLATE ή LC_ALL στην τιμή "C".


4.3.2. Κλάσεις χαρακτήρων

Οι κλάσεις χαρακτήρων μπορούν να καθοριστούν μέσα σε ορθογώνιες παρενθέσεις, με τη σύνταξη [:CLASS:], όπου το CLASS ορίζεται στο πρότυπο POSIX και έχει μια από τις τιμές

"alnum", "alpha", "ascii", "blank", "cntrl", "digit", "graph", "lower", "print", "punct", "space", "upper", "word" ή "git".

Μερικά παραδείγματα:

 
cathy ~> ls -ld [[:digit:]]*
drwxrwxr-x    2 cathy  cathy          4096 Apr 20 13:45 2/
 
cathy ~> ls -ld [[:upper:]]*
drwxrwxr--    3 cathy   cathy           4096 Sep 30  2001 Nautilus/
drwxrwxr-x    4 cathy   cathy           4096 Jul 11  2002 OpenOffice.org1.0/
-rw-rw-r--    1 cathy   cathy         997376 Apr 18 15:39 Schedule.sdc

Όταν η επιλογή φλοιού extglob ενεργοποιηθεί (μέσω της εσωτερικής εντολής shopt), τότε αναγνωρίζονται αρκετές λειτουργίες εκετατμένης ταύτισης προτύπων. Διαβάστε περισσότερα στις σελίδες πληροφόρησης του Bash, ενότητα Basic shell features->Shell Expansions->Filename Expansion->Pattern Matching.


4.4. Περίληψη

Οι κανονικές εκφράσεις είναι ισχυρά εργαλεία για την επιλογή συγκεριμένων γραμμών από αρχεία ή την έξοδο. Πολλές εντολές και εφαρμογές του UNIX χρησιμοποιούν κανονικές εκφράσεις, όπως τα vim, perl, η βάση δεδομένων PostgreSQL κλπ. Μπορούν να εισχθούν σε οποιαδήποτε γλώσσα ή εφαρμογή με τη βοήθεια εξωτερικών βιβλιοθηκών, και ακόμη είναι διαθέσιμες και σε μη-UNIX συστήματα. Για παράδειγμα, οι κανονικές εκφράσεις χρησιμοποιούνται στο λογιστικό φύλλο Excell του πακέτου MicroSoft Windows Office. Σε αυτό το κεφάλαιο προσεγγίσαμε την εντολή grep, που είναι απαραίτητη σε κάθε περιβάλλον UNIX.

Note

 Η εντολή grep μπορεί να κάνει πολύ περισσότερα από τις λίγες εργασίες που συζητήσαμε εδώ. Τη χρησιμοποιήσαμε μόνο ως παράδειγμα χειρισμού κανονικών εκφράσεων. Η έκδοση GNU grep συνοδεύεται από μεγάλη τεκμηρίωση που σας συνιστούμε να διαβάσετε!

Το Bash έχει ενσωματωμένα χαρακτηριστικά για ταύτιση προτύπων και μπορεί να αναγνωρίσει κλάσεις και εύρη χαρακτήρων. 


4.5. Ασκήσεις

Αυτές οι ασκήσεις θα σας βοηθήσουν να χειριστείτε κανονικές εκφράσεις.

1.      Εμφανίστε μια λίστα με όλους τους χρήστες στο σύστημά σας που έχουν το Bash ως προεπιλεγμένο φλοιό.

2.      Από το αρχείο /etc/group, εμφανίστε όλες τις γραμμές που περιέχουν τη συμβολοσειρά "daemon".

3.      Από το ίδιο αρχείο εμφανίστε όλες τις σειρές που δεν περιέχουν αυτή τη συμβολοσειρά.

4.      Εμφανίστε τις πληροφορίες του localhost από το αρχείο /etc/hosts, εμφανίστε τους αριθμούς γραμμών όπου υπάρχει η συμβολοσειρά και μετρήστε το πλήθος των ταυτίσεων.

5.      Εμφανίστε μια λίστα υποκαταλόγων του καταλόγου /usr/share/doc που περιέχουν πληροφορίες για φλοιούς.

6.      Πόσα αρχεία README περιέχουν αυτοί οι υποκατάλογοι; Μη μετρήσετε ονόματα στη μορφή "README.a_string".

7.      Με τη βοήθεια της grep κάντε μια λίστα των αρχείων του οικείου καταλόγου σας τα οποία τροποποιήθηκαν τις τελευταίες 10 ώρες, αλλά μην περιλάβετε τους υποκαταλόγους.

8.      Βάλτε τις εντολές σε ένα σενάριο που θα παράγει ένα κατανοητό αποτέλεσμα.

9.      Μπορείτε, με τη χρήση της grep να βρείτε εναλλακτική λύση για την εντολή wc -l;

10.  Με τη χρήση ενός πίνακα του συστήματος αρχείων (πχ το /etc/fstab), εμφανίστε τις τοπικές συσκευές δίσκων.

11.  Δημιουργείστε ένα σενάριο που ελέγχει αν υπάρχει κάποιος χρήστης στο αρχείο /etc/passwd. Προς το παρόν, μπορείτε να ορίσετε το όνομα του χρήστη μέσα στο σενάριο, δε χρειάζεται να δουλέψετε με ορίσματα και εντολές συνθήκης.

12.   Εμφανίστε τα αρχεία ρύθμισης στο κατάλογο /etc που περιέχουν αριθμούς στα ονόματά τους.


Κεφάλαιο 5. Ο συντάκτης ροής GNU sed 

Στο τέλος αυτού του κεφαλαίου θα γνωρίζετε τα παρακάτω θέματα:

·         Τι είναι ο sed;

·         Διαλογική χρήση του sed

·         Κανονικές εκφράσεις και σύνταξη ροής

·         Χρήση εντολών sed σε σενάρια

Note

Πρόκειται για εισαγωγή

 

Το κείμενο που ακολουθεί απέχει πολύ από το να είναι πλήρης και οριστικός οδηγός χρήσης του sed. Το κεφάλαιο αυτό περιλαμβάνεται για να μπορέσουμε να δείξουμε μερικά ενδιαφέροντα θέματα σχετικά με τα σενάρια σε επόμενα κεφάλαια, και επειδή κάθε ισχυρός χρήστης Linux πρέπει να γνωρίζει ορισμένα βασικά για αυτόν τον συντάκτη.

Για λεπτομερείς πληροφορίες, αναφερθείτε στις σελίδες πληροφόρησης και εγχειριδίου του sed.


5.1. Εισαγωγή

5.1.1. Τι είναι ο sed;

Ένας συντάκτης ροής (Stream EDitor) χρησιμοποιείται για την τροποποίηση κειμένου κατά την ανάγνωσή του από αρχείο ή από σωλήνωση. Το αποτέλεσμα αποστέλεται στη πρότυπη έξοδο. Η σύνταξη της εντολής sed δεν προβλέπει αρχείο εξόδου, αλλά το αποτέλεσμα μπορεί να αποθηκευτεί σε αρχείο με ανακατεύθυσνη της εξόδου. Ο συντάκτης δεν τροποποιεί την αρχική εσίσοδο.

Αυτό που ξεχωρίζει τον sed από άλλους συντάκτες, όπως ο vi ή ο ed, είναι η δυνατότητά του να φιλτράρει κείμενο που λαμβάνει από σωλήνωση. Δεν χρειάζεται να διαδράτε με τον συντάκτη, κατά την εκτέλεση, γι' αυτό το λόγο ο sed μερικές φορές λέγεται και συντάκτης δέσμης (batch editor). Αυτό το χαρακτηριστικό επιτρέπει τη χρήση εντολών τροποποίησης αρχείων μέσα σε σενάρια, πράγμα που διευκολύνει πολύ σε επαναλαμβανόμενες τροποποιήσεις αρχείων. Όταν πρέπει να γίνουν αλλαγές σε μεγάλο αριθμό αρχείων, ο sed είναι πολύ βοηθητικός.


5.1.2. Εντολές του sed 

Το πρόγραμμα sed μπορεί να εκτελέσει αντικαταστάσει, τροποποιήσεις και διαγραφές προτύπων κειμένου με τη χρήση κανονικών εκφράσεων, όπως στην εντολή grep; δείτε Ενότητα 4.2.

Οι εντολές είαι παρόμοιες με αυτές του συντάκτη vi:

Πίνακας 5-1. Εντολές sed 

Εντολή

Αποτέλεσμα

a\

Προσθήκη κειμένου μετά τη τρέχουσα γραμμή.

c\

Αντικατάσταση κειμένου τρέχουσας γραμμής με νέο κείμενο.

d

Διαγραφή κειμένου.

i\

Εισαγωγή κειμένου πριν τη τρέχουσα γραμμή.

p

Εμφάνιση κειμένου.

r

Ανάγνωση από αρχείο.

s

Εύρεση και αντικατάσταση κειμένου.

w

Εγγραφή σε αρχείο.

Εκτός από τις παραπάνω εντολές, υπάρχουν αρκετές επιλογές του sed. Μια σύνοψη φαίνεται παρακάτω:

Πίανκας 5-2. Επιλογές sed

Εντολή

Αποτέλεσμα

-e SCRIPT

Προσθέτει τις εντολές στο SCRIPT στο σύνολο των εντολών που θα εκτελεστούν κατά την επεξεργασία της εισόδου.

-f

Προσθέτει τις εντολές που περιλαμβάνονται στο αρχείο SCRIPT-FILE στο σύνολο των εντολών που θα εκτελεστούν κατά την επεξεργασία της εισόδου.

-n

Σιωπηλή κατάσταση.

-V

Εμφάνιση πληροφοριών έκδοσης και έξοδος.

Οι σελίδες πληροφοριών του sed περιέχουν περισσότερα στιοχεία, εδώ απλά παραθέτουμε τις συνηθέστερες εντολές και επιλογές. 


5.2. Διαλογική σύνταξη

5.2.1. Εμφάνιση γραμμών που περιέχουν ένα πρότυπο

Αυτό είναι κάτι που μπορείτε να κάνετε με τη grep, βέβαια, αλλά δεν μπορείτε να εκτελέσετε "εύρεση και αντκατάσταση". Αυτό σαν αρχή.

Αυτό είναι το αρχείο μας:

 
sandy ~> cat -n example
     1  This is the first line of an example text.
     2  It is a text with erors.
     3  Lots of erors.
     4  So much erors, all these erors are making me sick.
     5  This is a line not containing any errors.
     6  This is the last line.
 
sandy ~>

Θέλουμε ο sed να βρεί όλες τις γραμμές που περιέχουν το πρότυπο που αναζητούμε, στη περίπτωσή μας το "erors". Χρησιμοποιούμε την εντολή p:

 
sandy ~> sed  '/erors/p' example
This is the first line of an example text.
It is a text with erors.
It is a text with erors.
Lots of erors.
Lots of erors.
So much erors, all these erors are making me sick.
So much erors, all these erors are making me sick.
This is a line not containing any errors.
This is the last line.
 
sandy ~>

Όπως βλέπετε, ο sed δεν εμφανίζει όλο το αρχείο, αλλά τις γραμμές που περιέχουν το πρότυπο εμφανίζονται δύο φορές. Δεν θέλουμε αυτό. Αυτό που χρειαζόμαστε είναι η επιλογή -n:

 
sandy ~> sed -n '/erors/p' example
It is a text with erors.
Lots of erors.
So much erors, all these erors are making me sick.
 
sandy ~>

5.2.2. Διαγραφή γραμμών της εισόδου που περιέχουν ένα πρότυπο

Χρησιμποποιούμε το ίδιο αρχείο. Τώρα θέλουμε να εμφανίσουμε τις γραμμές που δεν περιέχουν το πρότυπο.

 
sandy ~> sed '/erors/d' example
This is the first line of an example text.
This is a line not containing any errors.
This is the last line.
 
sandy ~>

Η εντολή d αποκλείει αυτές τις γραμμές.

Η ταύτιση γραμμών που αρχίζουν και τελειώνουν με συγκεκριμένο πρότυπο εμφανίζεται ως εξής:

 
sandy ~> sed -n '/^This.*errors.$/p' example
This is a line not containing any errors.
 
sandy ~>

5.2.3. Διαστήματα γραμμών

Αυτή τη φορά θέλουμε να αφαιρέσουμε γραμμές που περιέχουν λάθη. Στο παράδειγμα είναι οι γραμμές 2 ως 4. Το διάστημα συνοδεύεται με την εντολή d:

 
sandy ~> sed '2,4d' example
This is the first line of an example text.
This is a line not containing any errors.
This is the last line.
 
sandy ~>

Για την εμφάνιση του αρχείου από κάποια γραμμή μέχρι το τέλος του αρχείου, δουλεύουμε ως εξής

sandy ~> sed '3,$d' example
This is the first line of an example text.
It is a text with erors.
 
sandy ~>

Αυτή η εντολή εμφανίζει τις δύο πρώτες γραμμές, δηλαδή διαγράφει τις γραμμές από τη τρίτη μέχρι τη τελευταία.

Η επόμενη εντολή εμφανίζει τη πρώτη γραμμή που περιέχει το πρότυπο "a text" και συνεχίζει μέχρι και τη γραμμή που περιέχει το πρότυπο "This":

 
sandy ~> sed -n '/a text/,/This/p' example
It is a text with erors.
Lots of erors.
So much erors, all these erors are making me sick.
This is a line not containing any errors.
 
sandy ~>

5.2.4. Εύρεση και αντικατάσταση με sed

Στο αρχείο του παραδείγματος, τώρα αντι να (απο-)επιλέγουμε τις γραμμές με λάθη, θα βρούμε τα λάθη και θα τα διορθώσουμε.

 
sandy ~> sed 's/erors/errors/' example
This is the first line of an example text.
It is a text with errors.
Lots of errors.
So much errors, all these erors are making me sick.
This is a line not containing any errors.
This is the last line.
 
sandy ~>

Όπως βλέπετε, στη γραμμή 4 δεν πετύχαμε ακριβώς, γιατί διορθώθηκε μόνο η πρώτη εμφάνιση του λάθους, ενώ το δέυτερο έμεινε αμετάβλητο. Με την εντολή g υποδεικνύουμε στο sed να εξετάσει όλη τη γραμμή και να μη σταματήσει στην πρώτη εμφάνιση του προτύπου.

 
sandy ~> sed 's/erors/errors/g' example
This is the first line of an example text.
It is a text with errors.
Lots of errors.
So much errors, all these errors are making me sick.
This is a line not containing any errors.
This is the last line.
 
sandy ~>

Για την εισάγουμε μια συμβολοσειρά στην αρχή κάθε γραμμής ενός αρχείου, για παράδειγμα όπως στο κείμενο που παρατίθεται σε e-mails:

 
sandy ~> sed 's/^/> /' example
> This is the first line of an example text.
> It is a text with erors.
> Lots of erors.
> So much erors, all these erors are making me sick.
> This is a line not containing any errors.
> This is the last line.
 
sandy ~>

Εισαγωγή κειμένου στο τέλος της γραμμής:

 
sandy ~> sed 's/$/EOL/' example
This is the first line of an example text.EOL
It is a text with erors.EOL
Lots of erors.EOL
So much erors, all these erors are making me sick.EOL
This is a line not containing any errors.EOL
This is the last line.EOL
 
sandy ~>

Πολλαπλές εντολές εύρεσης και αντικατάστασης διαχωρίζονται με επιλογή -e:

 
sandy ~> sed -e 's/erors/errors/g' -e 's/last/final/g' example
This is the first line of an example text.
It is a text with errors.
Lots of errors.
So much errors, all these errors are making me sick.
This is a line not containing any errors.
This is the final line.
 
sandy ~>

Να έχετε υπ' όψη οτι ως προεπιλογή ο sed στέλνει τα αποτελέσματά του στη πρότυπη έξοδο, δηλαδή πιθανότατα στη οθόνη. Αν θέλετε να αποθηκεύσετε το αποτέλεσμα σε ένα αρχείο πρέπει να το ανακατευθύνετε:

sed option 'some/expression' file_to_process > sed_output_in_a_file

Tip

Περισσότερα παραδείγματα

 

Αρκετά παραδείγματα χρήσης του sed μπορέιτε να βρείτε στα σενάρια εκκίνησης του συστήματός σας, τα οποία συνήθως βρίσκονται στους καταλόγους /etc/init.d ή /etc/rc.d/init.d. Μετακινηθείτε στο κατάλογο με αυτά τα σενέρια και εισάγετε τη παρακάτω εντολή:

grep sed *


5.3. Μη διαλογική σύνταξη

5.3.1. Ανάγνωση εντολών sed από αρχείο

Μια σειρά από εντολές sed μπορούν να τοποθετηθούν σε ένα αρχείο και να εκτελεστούν με την επιλογή -f. Κατά τη δημιουργία ενός τέτοιου αρχείου, βεβαιωθείτε οτι:

·         Δεν υπάρχουν κενά, tabs ή άλλα white spaces στο τέλος των γραμμών.

·         Δεν υπάρχουν εισαγωγικά.

·         Όταν εισάγουμε κείμενο για προσθήκη ή αντικατάσταση, όλες οι γραμμές τελειώνουν με backslash εκτός από τη τελευταία.


5.3.2. Εγγραφή σε αρχεία εξόδου

Η εγγραφή σε αρχεία εξόδου επιτυγχάνεται με τον τελεστή ανακατεύθυνσης >. Παρακάτω έχουμε ένα παράδειγμα δημιουργίας απλών αρχείων HTML από απλά αρχεία κειμένου:

 
sandy ~> cat script.sed
1i\
<html>\
<head><title>sed generated html</title></head>\
<body bgcolor="#ffffff">\
<pre>
$a\
</pre>\
</body>\
</html>
 
sandy ~> cat txt2html.sh
#!/bin/bash
 
# This is a simple script that you can use for converting text into HTML.
# First we take out all newline characters, so that the appending only happens
# once, then we replace the newlines.
 
echo "converting $1..."
 
SCRIPT="/home/sandy/scripts/script.sed"
NAME="$1"
TEMPFILE="/var/tmp/sed.$PID.tmp"
sed "s/\n/^M/" $1 | sed -f $SCRIPT | sed "s/^M/\n/" > $TEMPFILE
mv $TEMPFILE $NAME
 
echo "done."
 
sandy ~>

Η παράμετρος θέσης $1 κρατά το πρώτο όρισμα στη γραμμή εντολής που θα εισχθεί το όνομα του σεναρίου. Στη περίπτωσή μας είναι το όνομα του αρχείου κειμένου προς μετατροπή.

 
sandy ~> cat test
line1
line2
line3

Περισσότερα για τις παραμέτρους θέσης στο Κεφάλαιο 7.

 
sandy ~> txt2html.sh test
converting test...
done.
 
sandy ~> cat test
<html>
<head><title>sed generated html</title></head>
<body bgcolor="#ffffff">
<pre>
line1
line2
line3
</pre>
</body>
</html>
 
sandy ~>

Στη πραγματικότητα τα πράγματα είναι πιο σύνθετα. Εδώ απλά δίνουμε ένα παράδειγμα χρήσης του sed. Δείτε την Ενότητα 6.3 για μια πιο αποδοτική λύση σ' αυτό το πρόβλημα, με τις δομές BEGIN και END του awk.

Note

Εύκολος sed

 

Ορισμένοι σύγχρονοι συντάκτες, αναγνωριζουν τις εντολές και τις δομές του sed. Αυτό μπορεί να αποτελέσει μεγάλη βοήθεια, όταν για παράδειγμα ξεχνάτε το backslashes κλπ.


5.4. Περίληψη

Ο συντάκτης ροής sed είναι ισχυρό εργαλείο γραμμής εντολών, το οποίο διαχειρίζεται ροές δεδομένων: δέχεται είσοδο γραμμές κειμένου από αρχείο ή σωλήνωση. Αυτό καθιστά τον συντάκτη κατάλληλο για μη-διαλογική χρήση. Ο sed χρησιμοποιεί εντολές τύπου vi και αναγνωρίζει κανονικές εκφράσεις.

Ο sed μπορεί να διαβάσει εντολές από τη γραμμή εντολώνή από σενάρια. Χρησιμοποιείται συχνά για την εκτέλεση εργασιών εύρεσης και αντικατάστασης σε γραμμές που περιέχουν κάποιο πρότυπο.


5.5. Ασκήσεις

Αυτές οι ασκήσεις δείχνουν ακόμη μερικές δυνατότητες του sed.

1.      Εμφανίστε μια λίστα αρχείων στον κατάλογο scripts, που τελειώνουν σε ".sh". Προσέξτε μήπως το ls έχει ψευδώνυμο. Τοποθετείστε το αποτέλεσμα σε προσωρινό αρχείο.

2.      Κάντε μια λίστα αρχείων στο /usr/bin που έχουν το "a" σαν δεύτερο χαρακτήρα. Βάλτε το αποτέλεσμα σε ένα προσωρινό αρχείο.

3.      Διαγράψτε τις 3 πρώτες γραμμές από κάθε προσωρινό αρχείο.

4.      Εμφανίστε στην πρότυπη έξοδο μόνο τις γραμμές που περιέχουν το πρότυπο "an".

5.      Δημιουργείστε ένα αρχείο με εντολές sed που να εκτελούν τις δύο προηγούμενες εργασίες. Προσθέστε ακόμη μια εντολή σε αυτό το αρχείο που προσθέτει μια συμβολοσειρά όπως "*** This might have something to do with man and man pages ***" πριν από κάθε γραμμή που περιέχει το πρότυπο "man". Ελέγξτε τα αποτελέσματα.

6.      Χρησιμοποιούμε ως είσοδο μια πλήρη εμφάνιση (ls -l) του ριζικού καταλόγου (root directory, /). Δημιουργείστε ένα αρχείο με εντολές sed που ελέγχουν για στμβολικούς δεσμούς και απλά αρχεία. Αν ένα αρχείο είναι συμβολικός δεσμός, εισάγετε πριν μια γραμμή που να λέει "--This is a symlink--". Αν το αρχείο είναι απλό, εισάγετε πριν μια γραμμή που να λέει "<--- this is a plain file".

7.      Δημιουργείστε ένα σενάριο που δείχνει τις γραμμές ενός αρχείου που έχουν στο τέλος τους white spaces. Αυτό το σενάριο πρέπει να χρησιμοποιήσει ένα σενάριο sed και να εξηγεί στο χρήστη το αποτέλεσμα.


Κεφάλαιο 6. Η γλώσσα προγραμματισμού GNU awk 

Σε αυτό το κεφάλαιο συζητούμε:

·         Τι είναι η gawk?

·         Χρήση εντολών gawk στη γραμμή εντολών

·         Μορφοποίηση κειμένου με gawk

·         Χρήση κανονικών εκφράσεων με gawk

·         Gawk και σενάρια

·         Gawk και μεταβλητές

Note

Για μεγαλύτερη ευχαρίστηση

 

Όπως και με το sed, έτσι και για την awk έχουν γραφεί ολόκληρα βιβλία. Αυτή η εισαγωγή απέχει πολύ από το να είναι πλήρης και έχει απλά σαν στόχο να καταλάβετε τα παραδείγματα των επόμενων κεφαλαίων. Για περισσότερες πληρφορίες, η καλύτερη εκκίνηση είναι η τεκμηρίωση της  GNU awk: "GAWK: Effective AWK Programming: A User's Guide for GNU Awk".


6.1. Εκκίνηση με τη gawk

6.1.1. Τί είναι η gawk;

Η gawk είναι η GNU έκδοση της γλώσσας awk που διατίθεται σχεδόν με κάθε UNIX, και στην ουσία είνα ένας πιο ευέλικτος συντάκτης ροής. Συνήθως στο Linux η εντολή awk είναι απλά ένας δεσμός προς την εντολή gawk, επομένως οι δύο έννοιες ταυτίζονται.

Η βασική λειτουργία της awk είναι η αναζήτηση προτύπων σε αρχεία ή στη πρότυπη είσοδο/έξοδοs  Όταν υπάρχει ταύτιση κάποιου προτύπου τότε εκτελούνται κάποιες ενέργειες σε αυτή τη γραμμή.

Τα προγράμματα σην awk είναι διαφορετικά από ότι στις περισσότερες κοινές γλώσσες, γιατί τα προγράμματα awk οδηγούνται από τα δεδομένα (είναι "data-driven"): περιγράφετε τα δεδομένα που θέλετε να επεξεργαστείτε και τι θέλετε να κάνετε όταν θα τα βρείτε. Οι περισσότερες άλλες γλώσσες είναι διαδικαστικές ("procedural"). Πρέπει να περιγράψετε, με λεπτομέρεια, κάθε βήμα του προγράμματος. Συνήθως, στις διαδικαστικε γλώσσες είναι δύσκολη η περιγραφή των δεδομένων προς επεξεργασία. Γι' αυτό το λόγο, τα προγράμματα  awk είναι διανοητικά ευχάριστα στην ανάγνωση και στη συγγραφή.

Note

Τι σημαίνει;

 

Στη δεκαετία του 1970, τρείς προγραμματιστές συνεργάστηκαν για τη δημιουργία της γλώσσας. Τα επίθετά τους ήταν Aho, Weinberger και Kernighan. Η γλώσσα πήρε το όνομά της από τα αρχικά των επθέτων τους. Φανταστείτε αν είχαν επιλέξει άλλη σειρά στα αρχικά.. .


6.1.2. Εντολές gawk

Όταν εκτελείτε την εντολή awk, ορίζετε ένα πρόγραμμα awk που λέει στην awk τί να κάνει. Το πρόγραμμα αποτελείται από σειρές κανόνων. (Μπορεί επίσης να περιέχει ορισμούς συναρτήσεων, βρόχους, συνθήκες και άλλες δομές προσγραμματισμού, που για την ώρα παραλείπουμε). Κάθε κανόνας ορίζει ένα πρότυπο προς αναζήτηση και μια ενέργεια που πρέπει να γίνει όταν αυτό το πρότυπο βρεθεί.

Υπάρχουν διάφοροι τρόποι εκτέλεσης της awk. Αν το πρόγραμμα είναι σύντομο, ο ευκολότερος τρόπος είναι η γραμμή εντολών:

awk PROGRAM inputfile(s)

Αν πρέπει να γίνουν πολλές αλλαγές, πιθανώς τακτικά και σε πολλά αρχεία, είναι πιο εύκολο να αποθηκεύσουμε τις εντολές της awk σε ένα σενάριο. Αυτό εκτελείται ώς εξής:

awk -f PROGRAM-FILE inputfile(s)


6.2. Το πρόγραμμα print

6.2.1. Εμφάνιση επιλεγμένων πεδίων

Η εντολή print της awk εμφανίζει επιλεγμένα δεδομένα από το αρχείο εισόδου.

Όταν η awk διαβάζει μια γραμμή από ένα άρχείο, τεμαχίζει τη γραμμή σε πεδία, με βάση τον καθορισμένο διαχωριστή πεδίων εισόδου (input field separator), FS, που είναι μια μεταβλητή awk (δες Ενότητα 6.3.2). Η προεπιλεγμένη τιμή της μεταβλητής είναι ένα ή περισσότερα κενά ή στηλοθέτες (tabs).

Οι μεταβλητές $1, $2, $3, ..., $N παίρνουν την τιμή του πρώτου, δεύτερου τρίτου ... νιοστού πεδίου της γραμμής εισόδου. Η μεταβητή $0 (μηδέν) κρατά όλη τη γραμμή. Αυτό φαίνεται στη παρακάτω εικόνα, όπυ βλέπουμε έξι στήλες στην έξοδο μιας εντολής df:

Εικόνα 6-1. Πεδία στην awk

Εικόνα 6-1

Στην έξοδο της εντολής ls -l, υπάρχουν 8 στήλες. Η εντολή print χρησιμοποιεί τα πεδία ως εξής:

 
kelly@octarine ~/test> ls -l | awk '{ print $5 $8 }'
160orig
121script.sed
120temp_file
126test
120twolines
441txt2html.sh
 
kelly@octarine ~/test>

Αυτή η εντολή εμφάνισε τη πέμπτη στήλη, που περιέχει το μέγεθος του αρχείου, και τη τελευταία στήλη που περιέχει το όνομα του αρχείμου. Η έξοδος δεν είναι ιδιαίτερα ευανάγνωση εκτός και αν χωρίσουμε τα ονόματα των πεδίων με κόμμα. Σε αυτή τη περίπτωση μεταξύ των πεδίων στην έξοδο τοποθετείται ο προεπιλεγμένος διαχωριστής πεδίων, συνήθως ένα κενό.


6.2.2. Πεδία μορφοποίησης

Χωρίς μορφοποίηση, με χρήση μόνο του διαχωριστή πεδίων, η έξοδος είναι μάλλον φτωχή. Η εισαγωγή μερικών σχολίων βελτιώνει την έξοδο.

 
kelly@octarine ~/test> ls -ldh * | grep -v total | \ 
awk '{ print "Size is " $5 " bytes for " $9 }'
Size is 160 bytes for orig
Size is 121 bytes for script.sed
Size is 120 bytes for temp_file
Size is 126 bytes for test
Size is 120 bytes for twolines
Size is 441 bytes for txt2html.sh
 
kelly@octarine ~/test>

Σημειώστε τη χρήση του backslash, που επιτρέπει την επέκταση της γραμμής εντολών σε δεύτερη γραμμή. Δείτε την Ενότητα 3.3.2.

Η επιλογή -h στην εντολή ls χρησιμοποιείται για την εμφάνιση του μεγέθους των αρχείων σε κατανοητή μορφή.  Από την έξοδο αφαιρούμε τη γραμμή που εμφανίζει το συνολικό μέγεθος των αρχείων, όταν το όρισμα είναι όνομα καταλόγου. Επειδή η γραμμή είναι άχρηστη, προσθέτουμε ένα αστερίσκο. Επίσης προσθέτουμε την επιλογή -d για τον ίδιο λόγο, αν ο αστερίσκος επεκταθεί σε κατάλογο.

Μπορούμε να αφαιρέσουμε διάφορες στήλες ή να αλλάξουμε τη σειρά τους. Στο παρακάτω παράδειγμα εμφανίζονται τα διαμερίσματα ενός δίσκου.

 
kelly@octarine ~> df -h | sort -rnk 5 | head -3 | \ 
awk '{ print "Partition " $6 "\t: " $5 " full!" }'
Partition /var  : 86% full!
Partition /usr  : 85% full!
Partition /home : 70% full!
 
kelly@octarine ~>

Ο παρακάτω πίνακας δίνει μια σύνοψη των ειδικών χαρακτήρων μορφοποίησης:

Πίνακας 6-1. Χαρακτήρες μορφοποίησης της gawk

Ακολουθία

Σημασία

\a

Ήχος

\n

Αλλαγή γραμμής

\t

Στηλοθέτης (Tab)

Τα εισαγωγικά, το δολλάριο και οι άλλοι μεταχαρακτήρες πρέπει να ακυρώνονται με backslash.


6.2.3. Η εντολή print και κανονικές εκφράσεις

Μια κανονική έκφραση μπορεί να χρησιμοποιηθεί σαν πρότυπο αν περικλειστεί σε κάθετες (slashes). Η κανονική έκφραση ελέγχεται για ταύτιση με όλους τους χαρακτήρες της κάθε γραμμής. Η σύνταξη είναι ως εξής:

awk 'EXPRESSION { PROGRAM }' file(s)

Το παρακάτω παράδειγμα εμφανίζει μόνο πληροφορίες για τοπικούς δίσκους, αλλά όχι δικτυακών συστημάτων:

 
kelly is in ~> df -h | awk '/dev\/hd/ { print $6 "\t: " $5 }'
/       : 46%
/boot   : 10%
/opt    : 84%
/usr    : 97%
/var    : 73%
/.vol1  : 8%
 
kelly is in ~>

Οι κάθετοι πρέπει να ακυρώνονται επειδή έχεουν ειδική σημασία στην awk.

Ακολουθεί ένα παράδειγμα αναζήτησης στον κατάλογο /etc για αρχεία που καταλήγουν σε ".conf" και αρχίζουν με "a" ή "x", με χρήση κανονικών εκφράσεων:

 
kelly is in /etc> ls -l | awk '/\<(a|x).*\.conf$/ { print $9 }'
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf
 
kelly is in /etc>

Αυτό το παράδειγμα δείχνει την ειδική σημασία της τελείας (dot) στις κανονικές εκφράσεις: η πρώτη τελεία δείχνει οτι θέλουμε να αναζητήσουμε για οποιονδήποτε χαρακτήρα μετά τον αρχικό χαρακτήρα, ενώ η δεύτερη τελεία ακυρώνεται γιατί είναι τμήμα μιας συμβολοσειράς (της κατάληξης).


6.2.4. Ειδικά πρότυπα

Για να προσθέσουμε σχόλια πριν την έξοδο, χρησιμοποιούμε τη δήλωση BEGIN:

 
kelly is in /etc> ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf
 
kelly is in /etc>

Η δήλωση END μπορεί να χρησιμοποιηθεί για πρόσθεση σχολίων στο τέλος:

 
kelly is in /etc> ls -l | \
awk '/\<[a|x].*\.conf$/ { print $9 } END { print \
"Can I do anything else for you, mistress?" }'
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf
Can I do anything else for you, mistress?
 
kelly is in /etc>

6.2.5. Σενάρια gawk

Καθώς οι εντολές επικηκύνονται και πληθαίνουν, ίσως είναι καλύτερα να τις βάλουμε σε ένα σενάριο, ώστε να είναι επαναχρησιμοποιήσιμες. Ένα σενάριο awk περιέχει δηλώσεις awk που ορίζουν πρότυπα και ενέργειες.

Ως παράδειγμα, θα κτίσουμε μια έκθεση που μας ενημερώνει για υπερφορτωμένα διαμερίσματα. Δες Ενότητα 6.2.2.

 
kelly is in ~> cat diskrep.awk
BEGIN { print "*** WARNING WARNING WARNING ***" }
/\<[8|9][0-9]%/ { print "Partition " $6 "\t: " $5 " full!" }
END { print "*** Give money for new disks URGENTLY! ***" }
 
kelly is in ~> df -h | awk -f diskrep.awk
*** WARNING WARNING WARNING ***
Partition /usr  : 97% full!
*** Give money for new disks URGENTLY! ***
 
kelly is in ~>

Η awk πρώτα εμφανίσει το μήνυμα της αρχής, μετά μορφοποιεί που έχουν οκτώ ή εννέα στην αρχή μιας λέξης, και ακολουθεί άλλο ψηφίο και το σύμβολο επί τοις εκατό. Στο τέλος υπάρχει ακόμη ενα μήνυμα.

Note

Βοηθήματα σύνταξης

 

Η awk είναι γλώσσα προγραμματισμού. Το συντακτικό του αναγνωρίζεται από αρκετούς σύγρχονους συντάκτες.


6.3. Μεταβλητές gawk 

Για την επεξεργασία των αρχείων εισόδου, η awk χρησιμοποιεί διάφορες μεταβλητές, από τις οποίες μερικές είναι μόνο για ανάγνωση.


6.3.1. Ο διαχωριστής πεδίων εισόδου

Ο διαχωριστής εισόδου, που είναι είτε ένας απλός χαρακτήρας ή μια κανονική έκφραση, ελέγχει το τρόπο που η awk χωρίζει μια γραμμή εισόδου σε πεδία. Η γραμμή εισόδου ελέγχεται για ταυτίσεις  ου διαχωριστή εισόδου, και ως πεδία ορίζονται τα τμήματα μεταξύ των διαχωριστών εισόδου. 

Ο διαχωριστής εισόδου παρίσταται ως η προκαθορισμένη μεταβλητή FS. Σημειώστε οτι είναι διαφορετική από τη μεταβλητή FS των POSIX-συμβατών φλοιών.

Η τιμή του διαχωριστή πεδίων της awk μπορεί να τροποποιηθεί με τον τελεστή εκχώρησης =. Συχνά ο σωστός χρόνος γι' αυτό είναι στην αρχή της εκτέλεσης, πριν ξεκινήσει η επεξεργασία της εισόδου. Γι' αυτό χρησιμοποιούμε την δήλωση BEGIN.

Στο παρακάτω παράδειγμα, δημιουργούμε μια εντολή που εμφανίζει όλους τους χρήστες του συστήματος μαζί με μια περιγραφή:

 
kelly is in ~> awk 'BEGIN { FS=":" } { print $1 "\t" $5 }' /etc/passwd
--output omitted--
kelly   Kelly Smith
franky  Franky B.
eddy    Eddy White
willy   William Black
cathy   Catherine the Great
sandy   Sandy Li Wong
 
kelly is in ~>

Σε μορφή σεναρίου awk, θα έμοιαζε κάπως έτσι:

 
kelly is in ~> cat printnames.awk
BEGIN { FS=":" }
{ print $1 "\t" $5 }
 
kelly is in ~> awk -f printnames.awk /etc/passwd
--output omitted--

Η επιλογή διαχωριστή πεδίων πρέπει να γίνει προσεκτικά για την αποφυγή προβλημάτων. Σαν παράδειγμα, έστω οτι έχετε ως είσοδο γραμμές όπως αυτή:

"Sandy L. Wong, 64 Zoo St., Antwerp, 2000X"

Γράφετε μια εντολή ή ένα σενάριο, που εμφανίζει τα τρία πρώτα πεδία κάθε γραμμής:

awk 'BEGIN { FS="," } { print $1, $2, $3 }' inputfile

Αλλά κάποιος έχει PhD, και η γραμμή του είναι:

"Sandy L. Wong, PhD, 64 Zoo St., Antwerp, 2000X"

Η awk θα δώσει λάθος έξοδο. Εδώ πρέπει να χρησιμοποιήσετε προεπεξεργασία με awk ήr sed για να ομογενοποιήσετε την είσοδο.

Ο προεπιλεγμένος διαχωριστής πεδίων είναι ένα ή περισσότερα κενά ή στηλοθέτες (tabs).


6.3.2. Οι διαχωριστές εξόδου 

6.3.2.1. Ο διαχωριστής πεδίων εξόδου

Συνήθως τα πεδία στην έξοδο χωρίζονται με κενά. Αυτό γίνεται φανερό όταν χρησιμοποιείτε στη σωστή σύνταξη της δήλωσης print, όπου τα ορίσματα χωρίζονται με κόμμα.

 
kelly@octarine ~/test> cat test
record1         data1
record2         data2
 
kelly@octarine ~/test> awk '{ print $1 $2}' test
record1data1
record2data2
 
kelly@octarine ~/test> awk '{ print $1, $2}' test
record1 data1
record2 data2
 
kelly@octarine ~/test>

Αν δεν βάλετε κόμματα, η print αντιμετωπίζει τα ορίσματα εξόδου ως ένα ενιαίο πεδίο, και δεν τα χωρίζει με τον προεπιλεγμένο διαχωριστή εξόδου, OFS.

Ως διαχωριστής εξόδου μπορεί να χρησιμοποιηθεί οποιοσδήποτε χαρακτήρας.


6.3.2.2. Ο διαχωριστής γραμμών εξόδου

Η αλλαγή γραμμής στην είσοδο ορίζει και μια γραμμή εξόδου της δήλωσης print . Η δήλωση print τερματίζει τη γραμμή εξόδου με τον διαχωριστή γραμμών εξόδου, ORS. Η προεπιλεγμένη τιμή του διαχωριστή εξόδου είναι "\n", η αλλαγή γραμμής.

Η τιμή της ORS μπορεί να τροποποιηθεί:

 
kelly@octarine ~/test> awk 'BEGIN { OFS=";" ; ORS="\n-->\n" } \
{ print $1,$2}' test
record1;data1
-->
record2;data2
-->
 
kelly@octarine ~/test>

Αν η τιμή του ORS δεν περιέχει νέα γραμμή (newline), όλη η έξοδος θα εμφανιστεί σε μια ενιαία γραμμή.


6.3.3. Αριθμός γραμμών 

Η προκαθορισμένη μεταβλητή NR αποθηκεύει τον αριθμό των γραμμών που έχουμε επεξεργαστεί. Αυξάνεται μετά την ανάγνωση μιας γραμμής εισόδου. Μπορείτε να τη χρησιμοποιήσετε στο τέλος για να μετρήσετε τον συνολικό αριθμό γραμμών ή να αριθμήσετε τις γραμμές:

 
kelly@octarine ~/test> cat processed.awk
BEGIN { OFS="-" ; ORS="\n--> done\n" }
{ print "Record number " NR ":\t" $1,$2 }
END { print "Number of records processed: " NR }
 
kelly@octarine ~/test> awk -f processed.awk test
Record number 1:        record1-data1
--> done
Record number 2:        record2-data2
--> done
Number of records processed: 2
--> done
 
kelly@octarine ~/test>

6.3.4. Μεταβλητές ορισμένες από το χρήστη

Εκτός από τις προκαθορισμένες μεταβλητές, μπορείτε να ορίσετε και δικές σας. Όταν η awk συναντά μια αναφορά σε μια μεταβλητή που δεν υπάρχει, τότε η μεταβλητή δημιουργείται αυτόματα και  αρχικοποιείται με μια κενή συμβολοσειρά. Για όλες τις μετέπειτα αναφορές, η τιμή της μεταβλητής είναι αυτή που έχει εκχωρηθεί τελευταία. Οι τιμές μπορεί να είναι συμβολοσειρές ή αριθμοί. Τα πεδία των γραμμών εισόδου μπορεί να εκχωρηθούν σε μεταβλητές. 

Η εκχώρηση γίνεται με τον τελεστή = και σε συνδυασμό με άλλους τελεστές:

 
kelly@octarine ~> cat revenues
20021009        20021013        consultancy     BigComp         2500
20021015        20021020        training        EduComp         2000
20021112        20021123        appdev          SmartComp       10000
20021204        20021215        training        EduComp         5000
 
kelly@octarine ~> cat total.awk
{ total=total + $5 }
{ print "Send bill for " $5 " dollar to " $4 }
END { print "---------------------------------\nTotal revenue: " total }
 
kelly@octarine ~> awk -f total.awk test
Send bill for 2500 dollar to BigComp
Send bill for 2000 dollar to EduComp
Send bill for 10000 dollar to SmartComp
Send bill for 5000 dollar to EduComp
---------------------------------
Total revenue: 19500
 
kelly@octarine ~>

Οι συντμήσεις της C όπως VAR+= value είναι δεκτές.


6.3.5. Περισσότερα παραδείγματα

Το παράδειγμα της Ενότητας 5.3.2 γίνεται πολύ ευκολότερο με χρήση σεναρίων awk:

 
kelly@octarine ~/html> cat make-html-from-text.awk
BEGIN { print "<html>\n<head><title>Awk-generated HTML</title></head>\n<body bgcolor=\"#ffffff\">\n<pre>" }
{ print $0 }
END { print "</pre>\n</body>\n</html>" }

Και η εντολή για την εκτέλεση του σεναρίου είναι επίσης απλούστερη με την awk αντί του sed:

 
kelly@octarine ~/html> awk -f make-html-from-text.awk testfile > file.html

 

Tip

Παραδείγματα  awk στο σύστημά σας

 

Μπορείτε να αναζητήσετε μερικά σενάρια στο κατάλογο που περιέχει τα σενάρια εκκίνησης:

grep awk /etc/init.d/*


6.3.6. Το πρόγραμμα printf 

Για ακριβέστερο έλεγχο της μορφής της εξόδου μπορείτε χρησιμοποιήσετε τη printf. Η δήλωση printf μπορεί να ορίσει το εύρος του κάθε πεδίου, τη μορφή εκτύπωσης αριθμών (βάση, εκθέτη, πρόσημο, κλπ). Αυτό γίνεται με την παροχή μιας συμβολοσειράς μορφοποίησης.

Η σύνταξη είναι παρόμοια με αυτή της δήλωσης printf της γλώσσας C. Οι σελίδες πληροφοριών της gawk περιέχουν αρκετά στοιχεία.


6.4. Περίληψη

Η εφαρμογή gawk διερμηνεύει μια γλώσσα ειδικού σκοπού, με στόχο την αναμόρφωση αρχείων κειμένου, με τη χρήση λίγων μόνο εντολών. Είναι η δωρεάν έκδοση της γλώσσας  awk του UNIX

Περιλαμβάνει εργαλεία για την ανάγνωση αρχείων και την παραγωγή γραμμών χωρισμένων σε πεδία. Το πιο συχνά χρησιμοποιούμενο εργαλείο είναι το πρόγραμμα print.

Επιτρέπει  την άμεση δήλωση μεταβλητών και διαθέτει δυνατότητες για απλούς αριθμητικούς υπολογισμούς σχετικά  με το αρχείο εισόδου. Επίσης επιτρέπει τη δημιουργία σεναρίων awk για εργασίες στο υπόβαθρο.

Μερικά άλλα πράγματα που πρέπει να ξέρετε για την awk:

·         Η γλώσσα είναι γνωστή στους χρήστες του UNIX, αλλά πλέον, για παρόμοιες εργασίες, η gγλώσσα Perl χρησιμοποιείται όλο και πιο συχνά. Όμως η awk μαθαίνεται πολύ πιο γρήγορα επομένως παραμένει ενδιαφέρουσα για μικρές εφαρμογές.

·         Τόσο η Perl όσο και η awk έχουν τη φήμη οτι παράγουν δυσνόητα προγράμματα. Ακόμη και οι ίδιοι οι συγγραφείς των προγραμμάτων, μετά από κάποιο χρονικό διάστημα δυυκολέυονται να τα καταλάβουν αν δεν έχουν καλή τεκμηρίωση. Γι' αυτό να τεκμηριώνετε καλά τα προγράμματά σας! 


6.5. Ασκήσεις

Μερικά πρακτιοκά παραδείγματα όπου η awk μπορεί να είνα χρήσιμη.

1.      Σαν πρώτη άσκηση, δημιουργείστε ένα αρχείο εισόδου με γραμμές στη παρακάτω μορφή:

Username:Firstname:Lastname:Telephone number

2.      Δημιουργείστε μια εντολή awk που να μετατρέπει με τέτοια γραμμή σε εγγραφή LDAP στη μορφή:

 
dn: uid=Username, dc=example, dc=com
cn: Firstname Lastname
sn: Lastname
telephoneNumber: Telephone number

3.      Δημιουργείστε ένα σενάριο awk που να εκτελεί την ίδια εργασία.

4.      Δημιουργείστε ένα σενάριο Bash με χρήση awk και εντολών UNIX που να σας δείχνει τους τρείς πρώτους χρήστες που χρησιμοποιούν τον περισσότερο αποθηκευτικό χώρο στο κατάλογο /home (αν πρόκειται για ξεχωριστό διαμέρισμα, τροποποιείστε το σενάριο ανάλογα). Πρώτα εκτελέστε τις εντολές από τη γραμμή εντολών, μετά τοποθετήστε τις σε ένα σενάριο. Το σενάριο πρέπει να παράγει ευανάγνωστη έξοδο. Αν το σενάριο δουλέψει, στείλτε τα αποτελέσματα με email στο λογαριασμό σας (για παράδειγμα με την εντολή mail -s Disk space usage <you@your_comp> < result).

Αν τρέχει ο δαίμονας quota, μπορείτε να χρησιμοποιήσετε αυτό το δαίμονα, αλλιώς χρησιμοποιείστε τη εντπλή find.

5.      Δημιουργείστε μια έξοδο τύπου XML από μια λίστα με πεδία χωρισμένα με Tab (στηλοθέτες) στην ακόλουθη μορφή:

 
Meaning very long line with a lot of description
 
meaning another long line
 
othermeaning    more longline
 
testmeaning     looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line, but i mean really looooooooooooooooooooooooooooooooooooooooooooooooooong.
 

Η έξδος πρέπει να μοιάζει με:

 
<row>
<entry>Meaning</entry>
<entry>
very long line
</entry>
</row>
<row>
<entry>meaning</entry>
<entry>
long line
</entry>
</row>
<row>
<entryothermeaning</entry>
<entry>
more longline
</entry>
</row>
<row>
<entrytestmeaning</entry>
<entry>
looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong line, but i mean really looooooooooooooooooooooooooooooooooooooooooooooooooong.
</entry>
</row>

Επιπρόσθετα, αν γνωρίζετε XML, γράψτε σενάρια (δηλώσεις) BEGIN και END για τη συμπλήρωση του πίνακα. Το ίδιο μπορεί να γίνει σε HTML.


Κεφάλαιο 7. Δηλώσεις απόφασης

Σ’αυτό το κεφάλαιο θα μιλήσουμε για τη χρήση των δηλώσεων απόφασης στα σενάρια Bash. Αυτό περικλείει τα ακόλουθα θέματα : 

·         Χρήση της κατάστασης εξόδου μια εντολής

·         Σύγκριση και έλεγχος εισόδου και αρχείων

·         Δομές if/then/else 

·         Δομές if/then/elif/else 

·         Χρήση και έλεγχος των παραμέτρων θέσης

·         Ένθετες δηλώσεις if 

·         Λογικές εκφράσεις

·         Χρήση δηλώσεων case 


7.1. Εισαγωγή στο if

7.1.1. Γενικά

Κάποιες στιγμές χρειάζεται να ακολοθηθούν διαφορετικές πορείες ενεργειών σε ένα σενάριο φλοιού, ανάλογα με την επιτυχία ή την αποτυχία μιας εντολής. Η δόμηση της εντολής if  επιτρέπει να προσδορίσετε τέτοιες καταστάσεις.

Η πιο συμπαγής σύνταξη της εντολής if είναι :

if TEST-COMMANDS; then CONSEQUENT-COMMANDS; fi

Εκτελείται η λίστα των εντολών TEST-COMMANDS και αν η κατάσταση εξόδου είναι μηδέν, εκτελείται και η λίστα CONSEQUENT-COMMANDS. Η κατάσταση επιστροφής είναι η κατάσταση εξόδου της τελευταίας εντολής, ή είναι μηδέν, αν η συνθήκη δεν κρίθηκε αληθής.

Μια TEST-COMMAND συχνά περιέχει αριθμητικές ή αλφαριθμητικές συγκρίσεις, αλλά μπορεί επίσης να περιέχει οποιαδήποτε εντολή που επιστρέφει μηδενικό αποτέλεσμα όποτε πετυχαίνει και κάποια άλλα αποτελέσματα όταν αποτυγχάνει. Μοναδιαίες εκφράσεις χρησιμοποιούνται συχνά για να εξετάσουν το αποτέλεσμα ενός αρχείου. Αν το όρισμα FILE σε κάποιον όρο της συνθήκης είναι της μορφής /dev/fd/N, τότε ελέγχεται ο περιγραφέας αρχείου "N". Τα stdin, stdout και stderr και οι περιγραφείς τους μπορεί να χρησιμοποιηθούν στους ελέγχους.


7.1.1.1. Εκφράσεις που χρησιμοποιουνται στο if

Ο παρακάτω πίνακας περιέχει μια σύνοψη των αποκαλούμενων "όρων" που συνθέτουν μια TEST-COMMAND. Αυτοί οι όροι τοποθετούνται μέσα σε ορθογώνιες παρενθέσεις για να υποδείξουν τον έλεγχο μιας έκφρασης συνθήκης.

Table 7-1. Όροι συνθήκης

Όρος

Σημασία

[ -a FILE ]

True if FILE exists.

[ -b FILE ]

True if FILE exists and is a block-special file.

[ -c FILE ]

True if FILE exists and is a character-special file.

[ -d FILE ]

True if FILE exists and is a directory.

[ -e FILE ]

True if FILE exists.

[ -f FILE ]

True if FILE exists and is a regular file.

[ -g FILE ]

True if FILE exists and its SGID bit is set.

[ -h FILE ]

True if FILE exists and is a symbolic link.

[ -k FILE ]

True if FILE exists and its sticky bit is set.

[ -p FILE ]

True if FILE exists and is a named pipe (FIFO).

[ -r FILE ]

True if FILE exists and is readable.

[ -s FILE ]

True if FILE exists and has a size greater than zero.

[ -t FD ]

True if file descriptor FD is open and refers to a terminal.

[ -u FILE ]

True if FILE exists and its SUID (set user ID) bit is set.

[ -w FILE ]

True if FILE True if FILE exists and is writable.

[ -x FILE ]

True if FILE exists and is executable.

[ -O FILE ]

True if FILE exists and is owned by the effective user ID.

[ -G FILE ]

True if FILE exists and is owned by the effective group ID.

[ -L FILE ]

True if FILE exists and is a symbolic link.

[ -N FILE ]

True if FILE exists and has been modified since it was last read.

[ -S FILE ]

True if FILE exists and is a socket.

[ FILE1 -nt FILE2 ]

True if FILE1 has been changed more recently than FILE2, or if FILE1 exists and FILE2 does not.

[ FILE1 -ot FILE2 ]

True if FILE1 is older than FILE2, or is FILE2 exists and FILE1 does not.

[ FILE1 -ef FILE2 ]

True if FILE1 and FILE2 refer to the same device and inode numbers.

[ -o OPTIONNAME ]

True if shell option "OPTIONNAME" is enabled.

[ -z STRING ]

True of the length of "STRING" is zero.

[ -n STRING ] or [ STRING ]

True of the length of "STRING" is non-zero.

[ STRING1 == STRING2 ]

True if the strings are equal. "=" may be used instead of "==" for strict POSIX compliance.

[ STRING1 != STRING2 ]

True if the strings are not equal.

[ STRING1 < STRING2 ]

True if "STRING1" sorts before "STRING2" lexicographically in the current locale.

[ STRING1 > STRING2 ]

True if "STRING1" sorts after "STRING2" lexicographically in the current locale.

[ ARG1 OP ARG2 ]

"OP" is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if "ARG1" is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to "ARG2", respectively. "ARG1" and "ARG2" are integers.

Οι εκφρράσεις μπορούν να συνδυαστούν με τους παρακάτω τελεστές, που παρουσιάζονται με σειρά προεραιότητας.

Πίνακς 7-2. Συνδυασμός εκφράσεων

Λειτουργία

Αποτέλεσμα

[ ! EXPR ]

True if EXPR is false.

[ ( EXPR ) ]

Returns the value of EXPR. This may be used to override the normal precedence of operators.

[ EXPR1 -a EXPR2 ]

True if both EXPR1 and EXPR2 are true.

[ EXPR1 -o EXPR2 ]

True if either EXPR1 or EXPR2 is true.

Τα []η εσωτερική εντολή testαποτιμούν εκφράσεις συνθηκών χρησιμοποιώντας ένα σύνολο από κανόνες βασισμένους σε κάποιο αριθμό ορισμάτων. Περισσότερες πληροφορίες σ’άυτό το αντικείμενο μπορούν να βρεθούν στην τεκμιρίωση  Bash. Όπως η if κλείνει με fi , έτσι και τα εισαγωγικά πρέπει να κλείσουν αφού γραφούν οι συνθήκες.


7.1.1.2. Εντολές που ακολουθούν τη δήλωση then 

Η λίστα CONSEQUENT-COMMANDS που ακολουθεί την εντολή then μπορεί να είναι οποιαδήποτε έγκυρη εντολή UNIX, οποιοδήποτε εκτελέσιμο πρόγραμμα, οποιοδήποτε εκτελέσιμο σενάριο φλοιού ή οποιοδήποτε έκφραση φλοιού, με εξαίρεση το fi. Είναι σημαντικό να θυμάστε ότι τα τμήματα των then και if  είναι χωριστές εντολές στο φλοιό. Συνεπώς, όταν εισάγονται στην  γραμμή εντολών διαχωρίζονται με ;

Σε ένα σενάριο, τα διαφορετικά τμήματα της εντολής if  είναι συνήθως καλά διαχωρισμένα. Ακολουθούν μερικά απλά παραδείγματα.


7.1.1.3. Έλεγχος αρχείων

Το πρώτο παράδειγμα ελέγχει για την ύπαρξη ενός αρχείου:

 
anny ~> cat msgcheck.sh
#!/bin/bash
 
echo "This scripts checks the existence of the messages file."
echo "Checking..."
if [ -f /var/log/messages ]
  then
    echo "/var/log/messages exists."
fi
echo
echo "...done."
 
anny ~> ./msgcheck.sh
This scripts checks the existence of the messages file.
Checking...
/var/log/messages exists.
 
...done.

7.1.1.4. Έλεγχος επιλογών φλοιού

Μπορείτε να το προσθέσετε στα προσωπικά σας αρχεία ρύθμισης του Bash:

 
# These lines will print a message if the noclobber option is set:
 
if [ -o noclobber ]
  then
        echo "Your files are protected against accidental overwriting using redirection."
fi
 

 

Note

Το  περιβάλλον

 

Το παραπάνω παράδειγμα θα δουλέψει αν εισαχθεί στη γραμμή εντολών:

 
anny ~> if [ -o noclobber ] ; then echo ; echo "your files are protected
against overwriting." ; echo ; fi
 
your files are protected against overwriting.
 
anny ~>

Όμως, αν ελέγχετε συνθήκες που εξαρτώνται από το περιβάλλον, μπορεί να πάρετε διαφορετικό αποτέλεσμα αν εισάγετε την ίδια εντολή σε σενάριο, γιατί το σενάριο θα ανοίξει νέοι μη-διαλογικό φλοιό, στον οποίο οι ματαβλητές και οι επιλογές μπορεί να μη ρυθμίζονται αυτόματα. 


7.1.2. Απλές εφαρμογές του if

7.1.2.1. Έλεγχος κατάστασης εξόδου

Η μεταβλητή ? κρατά τη κατάσταση εξόδου (exit status) της εντολής που μόλις εκτελέστηκε (η πιο πρόσφατα τερματισθείσα διεργασία προσκηνίου). 

Το ακόλουθο παράδειγμα δείχνει ένα απλό έλεγχο:

 
anny ~> if [ $? -eq 0 ]
More input> then echo 'That was a good job!'
More input> fi
That was a good job!
 
anny ~>

Το επόμενο παράδειγμα δείχνει οτι οι TEST-COMMANDS μπορεί να είναι οποιαδήποτε UNIX εντολή που επιστρέφει κατάσταση εξόδου, και οτι το if και αυτό επιστρέφει κατάσταση εξόδου 0.:

 
anny ~> if ! grep $USER /etc/passwd
More input> then echo "your user account is not managed locally"; fi
your user account is not managed locally
 
anny > echo $?
0
 
anny >

Το ίδιο αποτέλεσμα μπορεί να ληφθεί ως εξής:

 
anny > grep $USER /etc/passwd
 
anny > if [ $? -ne 0 ] ; then echo "not a local account" ; fi
not a local account
 
anny >

7.1.2.2. Αριθμητικές συγκρίσεις

Τα παρακάτω παραδείγματα χρησιμοποιούν αριθμητικές συγκρίσεις:

 
anny > num=`wc -l work.txt`
 
anny > echo $num
201
 
anny > if [ "$num" -gt "150" ]
More input> then echo ; echo "you've worked hard enough for today."
More input> echo ; fi
 
you've worked hard enough for today.
 
 
anny >

Αυτό το σενάριο εκτελείται από τον δαίμονα cron κάθε Κυριακή. Αν η εβδομάδα είναι άρτια, μας υπενθυμίζει να βγάλουμε τα σκουπίδια:

 
#!/bin/bash
 
# Calculate the week number using the date command:
 
WEEKOFFSET=$[ $(date +"%V") % 2 ]
 
# Test if we have a remainder.  If not, this is an even week so send a message.
# Else, do nothing.
 
if [ $WEEKOFFSET -eq "0" ]; then
  echo "Sunday evening, put out the garbage cans." | mail -s "Garbage cans out" your@your_domain.org
 

7.1.2.3. Συγκρίσεις συμβολοσειρών

Ένα παράδειγμα σύγκρισης συμβολοσειρών για να ελέγξουμε το ID ενός χρήστη:

 
if [ "$(whoami)" != 'root' ]; then
        echo "You have no permission to run $0 as non-root user."
        exit 1;
fi

Στο Bash, μπορείτε να συντομεύσετε τη δομή. Το σύντομο ισοδύναμο του παραπάνω είναι:

 
[ "$(whoami)" != 'root' ] && ( echo you are using a non-privileged account; exit 1 )

Η έκφραση "&&" ορίζει τι πρέπει να γίνει αν ο έλεγχος είναι αληθής, ενώ η έκφραση "||" όταν είναι ψευδής.

Στις συγκρίσεις μπορούν να χρησιμοποιηθούν και κανονικές εκφράσεις:

 
anny > gender="female"
 
anny > if [[ "$gender" == f* ]]
More input> then echo "Pleasure to meet you, Madame."; fi
Pleasure to meet you, Madame.
 
anny >

 

Note

Πραγματικοί προγραμματιστές

 

Οι περισσότεροι προγραμματιστές θα προτιμούσαν να χρησιμοποιήσουν την εσωτερική εντολή test που ισοδυναμεί με τη χρήση ορθογώνιων παρενθέσεων.

 
test "$(whoami)" != 'root' && (echo you are using a non-privileged account; exit 1)

Στις σελίδες τεκμηρίωσης του Bash θα βρείτε πληροφορίες για ταύτιση προτύπων με τις δομές "(( EXPRESSION ))" και "[[ EXPRESSION ]]".


7.2. Προχωρημένη χρήση του if

7.2.1. Δομές if/then/else 

7.2.1.1. Χαζό παράδειγμα

Αυτή η δομή επιτρέπει την εκτέλεση μιας ενέργειας αν οι έλεγχοι της εντολής if είναι αληθείς, και άλλης αν οι έλεγχοι είναι ψευδείς. Ένα παράδειγμα:

 
freddy scripts> gender="male"
 
freddy scripts> if [[ "$gender" == "f*" ]]
More input> then echo "Pleasure to meet you, Madame."
More input> else echo "How come the lady hasn't got a drink yet?"
More input> fi
How come the lady hasn't got a drink yet?
 
freddy scripts>

Αυτή είναι η πλήρης μορφή της δήλωσης if/then/else:

if TEST-COMMANDS; then

CONSEQUENT-COMMANDS;

else ALTERNATE-CONSEQUENT-COMMANDS;

fi

Όπως η λίστα CONSEQUENT-COMMANDS ακολουθεί τη δήλωση then, αντίστοχια η λίστα ALTERNATE-CONSEQUENT-COMMANDS ακολουθεί τη δήλωση else και μπορεί να περιέχει οποιαδήποτε εντολή τύπου UNIX που επιστρέφει κατάσταση εξόδου.

Ακόμη ένα παράδειγμα, επέκταση του παραδείγματος της Ενότητας 7.1.2.1:

 
anny ~> su -
Password:
[root@elegance root]# if ! grep ^$USER /etc/passwd 1> /dev/null
> then echo "your user account is not managed locally"
> else echo "your account is managed from the local /etc/passwd file"
> fi
your account is managed from the local /etc/passwd file
[root@elegance root]#

Μεταπηδούμε στο λογαριασμό root για να δείξουμε το αποτέλεσμα της δήλωσης else - συνήθως το root είναι τοπικός λογαριαμός ενώ οι λογαριασμοί χρηστών μπορεί να βρίσκονται σε κάποιο διακομιστή LDAP.


7.2.1.2. Έλεγχος ορισμάτων γραμμής εντολών

Αντί να ορίζουμε τιμές μεταβλητών πριν ή κατά την εκτέλεση ενός σεναρίου, είναι συχνά πιο κομψό να ορίζουμε τις τιμές των μεταβλητών στη γραμμή εντολών.

Γι' αυτό το σκοπό χρησιμοποιούμε τις παραμέτρους θέσης $1, $2, ..., $N. Η παράμετρος $# κρατά τον αριθμό των ορισμάτων της γραμμής εντολών, ενώ η $0 περιέχει το όνομα του σεναρίου.

Ακολουθεί ένα απλό παράδειγμα:

Εικόνα 7-1. Έλεγχος ορισμάτων γραμμής εντολών με if

Εικόνα 7-1

Να ένα άλλο παράδειγμα, με δύο ορίσματα:

 
anny ~> cat weight.sh
#!/bin/bash
 
# This script prints a message about your weight if you give it your
# weight in kilos and hight in centimeters.
 
weight="$1"
height="$2"
idealweight=$[$height - 110]
 
if [ $weight -le $idealweight ] ; then
  echo "You should eat a bit more fat."
else
  echo "You should eat a bit more fruit."
fi
 
anny ~> bash -x weight.sh 55 169
+ weight=55
+ height=169
+ idealweight=59
+ '[' 55 -le 59 ']'
+ echo 'You should eat a bit more fat.'
You should eat a bit more fat.

7.2.1.3. Έλεγχος αριθμού ορισμάτων

Το ακόλουθο παράδειγμα δείχνει μια τροποποίηση που προηγούμενου σεναρίου ώστε να εμφανίζει ένα μήνυμα χρήσης αν ο αριθμός ορισμάτων είναι διάφορος του 2:

 
anny ~> cat weight.sh
#!/bin/bash
 
# This script prints a message about your weight if you give it your
# weight in kilos and hight in centimeters.
 
if [ ! $# == 2 ]; then
  echo "Usage: $0 weight_in_kilos length_in_centimeters"
  exit
fi
 
weight="$1"
height="$2"
idealweight=$[$height - 110]
 
if [ $weight -le $idealweight ] ; then
  echo "You should eat a bit more fat."
else
  echo "You should eat a bit more fruit."
fi
 
anny ~> weight.sh 70 150
You should eat a bit more fruit.
 
anny ~> weight.sh 70 150 33
Usage: ./weight.sh weight_in_kilos length_in_centimeters

Το πρώτο όρισμα ονομάζεται $1, το δεύτερο $2 κλπ.. Ο συνολικός αριθμός ορισμάτων ονομάζεται $#.

Δείτε την ενότητα Ενότητα 7.2.5 ένα κομψότερο τρόπο εμφάνισης μηνυμάτων χρήσης.


7.2.1.4. Έλεγχος ύπαρξης αρχείου

Αυτό γίνεται σε πολλά σενάρια, αφού δεν εει νόημα να ξεκινήσουμε μια εργασία αν λείπουν τα δεδομένα που θα επεξεργαστεί:

 
#!/bin/bash
 
# This script gives information about a file.
 
FILENAME="$1"
 
echo "Properties for $FILENAME:"
 
if [ -f $FILENAME ]; then
  echo "Size is $(ls -lh $FILENAME | awk '{ print $5 }')"
  echo "Type is $(file $FILENAME | cut -d":" -f2 -)"
  echo "Inode number is $(ls -i $FILENAME | cut -d" " -f1 -)"
  echo "$(df -h $FILENAME | grep -v Mounted | awk '{ print "On",$1", \
which is mounted as the",$6,"partition."}')"
else
  echo "File does not exist."
fi

Σημειώστε οτι το όνομα αρχείου είναι μια μεταβλητή που λαμβάνει την τιμή της από το πρώτο όρισμα του σεναρίου. Εναλλακτικά, τα ανόματα των αρχείων μπορούν να αποθηκε'υονται σε μεταβλητές στην αρχή των σεναρίων, αν πρόκειται για σταθερά ονόματα. Ακόμη, το πρώτο όρισμα θα μπορούσε να χρησιμοποπιηθεί απ' ευθε'ίας, χωρίς τη παρεμβολή της μεταβλητής.


7.2.2. Δομές if/then/elif/else 

7.2.2.1. Γενικά

Αυτή είναι η πλήρης μορφή της δήλωσης if:

if TEST-COMMANDS; then

CONSEQUENT-COMMANDS;

elif MORE-TEST-COMMANDS; then

MORE-CONSEQUENT-COMMANDS;

else ALTERNATE-CONSEQUENT-COMMANDS;

fi

Η λίστα TEST-COMMANDS εκτελείται, και μετά, αν η κατάσταση εξόδου είναι μηδέν, εκτελείται η λίστα CONSEQUENT-COMMANDS. Αν η εκτέλεση της λίστας ΤEST-COMMANDS επιστρέψει μη-μηδιενική κατάσταση, εκτελείται η λίστα MORE-TEST-COMMANDS της δομής elif. Αν η εκτέλεση της αντίστοιχη λίστας επιστρέψει κατάσταση μηδέν τότε εκτελέιται η λίστα  MORE-CONSEQUENT-COMMANDS. Μπορεί να υπάρχουν διαδοχικές δομές elif οι οποίες εικτελούνται με τη σειρά. Αν η δομή else ακολουθείται από μια λίστα ALTERNATE-CONSEQUENT-COMMANDS, και η τελική εντολή της τελευταίας δομής if ή elif έχει μη-μηδενική κατάσταση εξόδου τότε η λίστα ALTERNATE-CONSEQUENT-COMMANDS εκτελείται. Η κατάσταση εξόδου είναι αυτή της τελευταίας εντολής που εκετλέστηκε, ή μηδέν αν καμμία συνθήκη δεν βρέθηκε αληθής.


7.2.2.2. Παράδειγμα

Αυτό το παράδειγμα μπορείτε να το βάλετε στο crontab σας για καθημερινή εκτέλεση:

 
anny /etc/cron.daily> cat disktest.sh
#!/bin/bash
 
# This script does a very simple test for checking disk space.
 
space=`df -h | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1 -`
alertvalue="80"
 
if [ "$space" -ge "$alertvalue" ]; then
  echo "At least one of my disks is nearly full!" | mail -s "daily diskcheck" root
else
  echo "Disk space normal" | mail -s "daily diskcheck" root
fi

7.2.3. Ένθετες δηλώσεις if 

Μέσα σε μια δήλωση if, μπορείτε να έχετε μια νέα δήλωση if. Μπορείτε να χρησιμοποιήσετε όσα επίπεδα ένθετων ifs θέλετε.

Αυτό είναι ένα παράδειγμα ελέγχου δίσεκτων ετών:

 
anny ~/testdir> cat testleap.sh
#!/bin/bash
# This script will test if we're in a leap year or not.
 
year=`date +%Y`
 
if [ $[$year % 400 ] -eq "0" ]; then
  echo "This is a leap year.  February has 29 days."
elif [ $[$year % 4 ] -eq 0 ]; then
        if [ $[$year % 100] -ne 0 ]; then
          echo "This is a leap year, February has 29 days."
        else
          echo "This is not a leap year.  February has 28 days."
        fi
else
  echo "This is not a leap year.  February has 28 days."
fi
 
anny ~/testdir> date
Tue Jan 14 20:37:55 CET 2003
 
anny ~/testdir> testleap.sh
This is not a leap year.

7.2.4. Λογικές πράξεις

Το παραπάνω σενάριο μπορεί να συντομευθεί με τη χρήση λογικών τελεστών "AND" (&&) και "OR" (||).

Εικόνα 7-2. Παράδειγμα χρήσης λογικών τελεστών

Εικόνα 7-2

Για τον έλεγχο αριθμητικών εκφράσεων χρησιμοποιούμε διπλές παρενθέσεις, δες Ενότητα 3.4.6. Αυτό ισοδυναμέι με χρήση της δήλωσης let. Προσοχή να μη χρησιμοποιήσετε ορθογώνιες παρενθέσεις εδώ. Αν προσπαθήσετε κάτι σαν $[$year % 400], δεν θα λειτουργήσει γιατί οι ορθογώνιες καμπύλες δεν παριστούν μια εντολή.

Μεταξύ άλλων συντακτών, ο gvim υποστηρίζει χρωματικούς κώδικες που βοηθούν στην αναγνώριση τέτοιων σφαλμάτων.


7.2.5. Χρήση της δήλωσης exit με το if

Ήδη συναντήσαμε εν συντομία την δήλωση exit στην Ενότητα 7.2.1.3Τερματίζει την εκτέλεση ολόκληρου του σενερίου. Χρησιμοποιείται συνήθως όταν αυτό που εισάγει ο χρήστης είναι λανθασμένο, εάν μια δήλωση δεν εκτελέστηκε επιτυχημένα ή αν εντοπίστηκε κάποιο άλλο λάθος.

Η δήλωση exit παίρνει έναν προαιρετικό όρσιμα. Αυτό το όρισμα είναι ένας ακέραιος κωδικός κατάστασης εξόδου, που μεταφέρεται πίσω στη γονική διεργασία και αποθηκεύεται στην μεταβλητή $?.

Ένα μηδενικό όρισμα σημαίνει ότι το σενάριο εκτελέστηκε επιτυχημένα. Οποιαδήποτε άλλη τιμή μπορεί να χρησιμοποιηθεί από τους προγραμματιστές για να δώσει διαφορετικά μηνύματα πίσω στον γονέα, έτσι ώστε να μπορούν να ακολουθηθούν διαφορετικές πορείες ενεργειών ανάλογα με την αποτυχία ή την επιτυχία της θυγατρικής διεργασίας. Αν δεν δοθεί κανέαν όρισμα στην εντολή exit, ο  γονικός φλοιός χρησιμοποιεί την τρέχουσα τιμή της μεταβλητής $?.

Παρακάτω είναι ένα παράδειγμα με το ελαφρά τροποποιημένο σενάριο penguin.sh, το οποίο στέλνει την κατάσταση εξόδου του πίσω στον γονέα, feed.sh:

 
anny ~/testdir> cat penguin.sh
#!/bin/bash
                                                                                                 
# This script lets you present different menus to Tux.  He will only be happy
# when given a fish.  We've also added a dolphin and (presumably) a camel.
                                                                                                 
if [ "$menu" == "fish" ]; then
  if [ "$animal" == "penguin" ]; then
    echo "Hmmmmmm fish... Tux happy!"
  elif [ "$animal" == "dolphin" ]; then
    echo "Pweetpeettreetppeterdepweet!"
  else
    echo "*prrrrrrrt*"
  fi
else
  if [ "$animal" == "penguin" ]; then
    echo "Tux don't like that.  Tux wants fish!"
    exit 1
  elif [ "$animal" == "dolphin" ]; then
    echo "Pweepwishpeeterdepweet!"
    exit 2
  else
    echo "Will you read this sign?!"
    exit 3
  fi
fi

Το σενάριο αυτό καλείται από το επόμενο, που εξάγει τις μεταβλητές menu και animal:

 
anny ~/testdir> cat feed.sh
#!/bin/bash
# This script acts upon the exit status given by penguin.sh
                                                                                                 
export menu="$1"
export animal="$2"
                                                                                                 
feed="/nethome/anny/testdir/penguin.sh"
                                                                                                 
$feed $menu $animal
                                                                                                 
case $? in
                                                                                                 
1)
  echo "Guard: You'd better give'm a fish, less they get violent..."
  ;;
2)
  echo "Guard: It's because of people like you that they are leaving earth all the time..."
  ;;
3)
  echo "Guard: Buy the food that the Zoo provides for the animals, you ***, how
do you think we survive?"
  ;;
*)
  echo "Guard: Don't forget the guide!"
  ;;
esac
                                                                                            
     
anny ~/testdir> ./feed.sh apple penguin
Tux don't like that.  Tux wants fish!
Guard: You'd better give'm a fish, less they get violent...

Όπως βλέπετε, οι κωδικοί κατάστασης εξόδου μπορούν να επιλεχθούν αυθαίρετα. . Οι υπάρχουσες εντολές συνήθως έχουν μια σειρά καθορισμένων κωδικών, δείτε το εγχειρίδιο προγραμματιστή κάθε εντολής για περισσότερες λεπτομέρειες.


7.3. Χρήση δηλώσεων case 

7.3.1. Απλοποιημένες συνθήκες

Οι ένθετες δηλώσεις if μπορεί να είναι καλές, αλλά όσο μεγαλώνει ο αριθμός των επιλογών, γίνονται μάλλον περίπλοκες. Για πολλαπλές επιλογές χρησιμοποιούμε τη case :

case EXPRESSION in CASE1) COMMAND-LIST;; CASE2) COMMAND-LIST;; ... CASEN) COMMAND-LIST;; esac

Κάθε περίπτωση ορίζεται από μια έκφραση προς ταύτιση. Εκτελούνται οι εντολές στο COMMAND-LIST που ακολουθεί τη πρώτη επιτυχημένη ταύτιση. Το σύμβολο  "|" χρησιμοποιείται για το χωρισμό πολλαπλών εκφράσεων, και ο τελεστής ")" τερματίζει τη λίστα των εκφράσεων. Κάθε περίπτωση μαζί με τις εκφράσεις και τις εντολές της λέγεται μια πρόταση (clause). Κάθε πρόταση τελειώνει με ";;". Κάθε δήλωση case τερματίζεται με δήλωση esac.

Στο παράδειγμα, δείχνουμε τη χρήση της case για την αποστολή πιο κατανοητών μηνυμάτων με το σενάριο disktest.sh:

 
anny ~/testdir> cat disktest.sh
#!/bin/bash
 
# This script does a very simple test for checking disk space.
 
space=`df -h | awk '{print $5}' | grep % | grep -v Use | sort -n | tail -1 | cut -d "%" -f1 -`
 
case $space in
[1-6]*)
  Message="All is quiet."
  ;;
[7-8]*)
  Message="Start thinking about cleaning out some stuff.  There's a partition that is $space % full."
  ;;
9[1-8])
  Message="Better hurry with that new disk...  One partition is $space % full."
 ;;
99)
  Message="I'm drowning here!  There's a partition at $space %!"
  ;;
*)
  Message="I seem to be running with an nonexitent amount of disk space..."
  ;;
esac
 
echo $Message | mail -s "disk report `date`" anny
 
anny ~/testdir>
You have new mail.
 
anny ~/testdir> tail -16 /var/spool/mail/anny
From anny@octarine Tue Jan 14 22:10:47 2003
Return-Path: <anny@octarine>
Received: from octarine (localhost [127.0.0.1])
        by octarine (8.12.5/8.12.5) with ESMTP id h0ELAlBG020414
        for <anny@octarine>; Tue, 14 Jan 2003 22:10:47 +0100
Received: (from anny@localhost)
        by octarine (8.12.5/8.12.5/Submit) id h0ELAltn020413
        for anny; Tue, 14 Jan 2003 22:10:47 +0100
Date: Tue, 14 Jan 2003 22:10:47 +0100
From: Anny <anny@octarine>
Message-Id: <200301142110.h0ELAltn020413@octarine>
To: anny@octarine
Subject: disk report Tue Jan 14 22:10:47 CET 2003
 
Start thinking about cleaning out some stuff.  There's a partition that is 87 % full.
 
anny ~/testdir>

Βέβαια θα μπορούσατε να ανοίξετε το πρόγραμμα των mail σας για να ελέγξετε τα αποτελέσματα. Αυτό είναι απλά για να αποδείξει ότι το script στέλνει ένα ικανοποιητικό mail με επικεφαλίδες "To:", "Subject:" και "From:".

Αρκετά περισσότερα παραδείγματα χρησιμοποιώντας τη δήλωση case μπορούν να βρεθούν στον κατάλογο σεναρίων εκκίνησης του συστήματός σας. Τα σενάρια εκκίνησης χρησιμοποιούν τις περπτώσεις start και stop για να εκκινήσουν ή να τερματίσουν μια διεργασία του συστήματος. Ένα θεωρητικό παράδειγμα μπορεί να βρεθεί στηνν επόμενη ενότητα.


7.3.2. Παράδειγμα σεναρίου εκκίνησης

Τα σενάρια εκκίνησης συχνά χρησιμοποιούν τις δηλώσεις case για την εκκίνηση, τερματισμό και διερεύνηση της κατάστασης υπηρεσιών. Ακολουθεί ένα απόσπασμα από το σενάριο που εκκινεί το Anacron, ένα δαίμονα που εκτελεί περιοδικά εντολές, με τη συχνότητα να ορίζεται σε ημέρες.

 
case "$1" in
        start)
            start
            ;;
         
        stop)
            stop
            ;;
         
        status)
            status anacron
            ;;
        restart)
            stop
            start
            ;;
        condrestart)
            if test "x`pidof anacron`" != x; then
                stop
                start
            fi
            ;;
         
        *)
            echo $"Usage: $0 {start|stop|restart|condrestart|status}"
            exit 1
 
esac

Οι εργασίες που εκτελούνται σε κάθε περίπτωση, όπως τερματισμός και εκκίνηση του δαίμονα, ορίζονται ως συναρτήσεις. Δες το Κεφάλαιο 11 για περισσότερες εξηγήσεις Σε άλλες διανομές του Linux μπορεί οι εργασίες να εκτελούνται χωρίς τη μεσολάβηση συναρτήσεων. 


7.4. Περίληψη

Σ’αυτό το κεφάλαιο μάθαμε πώς να κατασκευάζουμε συνθήκες μέσα σε σενάρια ώστε να εκτελούνται διαφορετικές ενέργειες ανάλογα με την αποτυχία ή την επιτυχία μιας εντολής. Οι ενέργειες μπορούν  να  καθοριστούν χρησιμοποιώντας την έκφραση if. Αυτό σας επιτρέπει να πραγματοποιείτε αριθμητικές και αλφαριθμητικέ συγκρίσεις, έλεγχο κώδικα κατάστασης εξόδου, έλεγχο εισόδου και αρχείων που απαιτούνταιι από το σενάριο.

Συχνά ένας απλός έλεγχος if/then/fi συχνά πριν από κάποιες εντολές σε ένα σενάριο φλοιού εμποδίζει την δημιουργία εξόδου, ώστε το σενάριο να μπορεί να εκτελεστεί στο παρασκήνιο ή μέσω της υπηρεσίας cron. Πιο πολύπλοκοι ορισμοί ή συνθήκες τοποθετούνται συνήθως σε δηλώσεις case.

Μετά από τον επιτυχημένο έλεγχο συνθηκών, το σενάριο μπορεί να πληροφορήσει ρητά την γονική διεργασία με την κατάσταση εξόδου exit 0. Μετά από αποτυχία οποιοσδήποτε άλλος κωδικός μπορεί να επιστραφεί. Με βάση τον κώδικα κατάστασης, η γονική διεργασία μπορεί να εκτελέσει τη κατάλληλη ενέργεια..


7.5. Ασκήσεις

Κάποιες ιδέες για να σας δώσουν έναυσμα στη χρησιμοποίηση του if στα σενάρια:

1.      Χρησιμοποιείστε μια δομή if/then/elif/else που να εμφανίζει πληροφορίες για τον τρέχοντα μήνα. Το σενάριο πρέπει να εμφανίζει τον αριθμό των ημερών αυτού του μήνα και να δίνει για δίσεκτα χρόνια αν ο τρέχων μήνας είναι Φεβρουάριος.

2.      Κάντε το ίδιο, χρησιμοποιώντας μια δήλωση case και μια εναλλακτική χρήση της εντολής date..

3.      Τροποποιείστε το /etc/profile έτσι ώστε να εμφανίζεται ένα ειδικό μήνυμα καλωσορίσματος όταν συνδέεται στο σύστημα ο root.

4.      Τροποποιείστε το σενάριο leaptest.sh από την Ενότητα 7.2.4 έτσι ώστε να απαιτεί ένα όρισμα, το έτος. Ελέγξτε ότι εισαγεται ακριβώς ένα όρισμα προμηθεύεται.

5.      Γράψτε ένα σενάριο που να ονομάζεται whichdaemon.sh το οποίο θα ελέγχει αν το httpd και το init εκτελούνται στο σύστημά σας. Εάν εκτελείται το httpd τρέχει, το σενάριο πρέπει να εμφανίζει ένα μήνυμα όπως, "This machine is running a web server." Χρησιμοποιείστε το ps για έλεγχο των δειργασιών.

6.      Γράψτε ένα σενάριο που να κάνει ένα αντίγραφο του οικείου καταλόγουσε μια απομακρυσμένο υπολογιστή συσκευή χρησιμοποιώντας το scp. Το σενάριο πρέπει να δίνει πληροφορίες σε ένα αρχείο καταγραφής, για παράδειγμα ~/log/homebackup.log. Αν δεν έχετε δεύτερο υπολογιστή για να στείλετε το αντίγραφο, χρησιμοποίησε το scp δοκιμάσεε να το αντιγράψετε στον ίδιο υπολογιστή. Αυτό απαιτεί κλειδιά SSH ανάμεσα στα δύο μέρη, ή αλλιώς πρέπει να εισαγετε κάποιον κωδικό πρόσβασης. Η δημιουργία κλειδιών SSH επεξηγείται στο man ssh-keygen.

Το σενάριο πρέπει να χρησιμοποιήσει το tar cf για την δημιουργία του εφεδρικού αρχείου και το gzip ή bzip2 για τη συμπίεση του αρχείου .tar. Βάλτε όλα τα ονόματα αρχείων σε μεταβλητές. Βάλτε το όνομα του απομακρυσμένου διακομιστή και του απομακρυσμένου καταλόγου σε μια μεταβλητή. Αυτό θα κάνει ευκολότερο να επαναχρησιμοποιήσετε το σενάριο ή να κάνετε αλλαγές στο μέλλον.

Το σενάριο πρέπει να ελέγξει την ύπαρξη κάποιου συμπιεσμένου αρχείου. Αν αυτό υπάρχει ήδη τότε το διαγράφουμε ώστε να εμποδίσουμε δημιουργία μηνύματος εξόδου.

Το σενάριο πρέπει επίσης να ελέγξει για διαθέσιμο ελεύθερο χώρο στο δίσκο. Θυμήθείτε ότι μπορείτε να έχετε ανά πάσα στιγμή τα δεδομένα στον προσωπικό σας κατάλογο, τα δεδομένα στο αρχείο .tar και τα δεδομένα σε συμπιεσμένη μορφή, όλα μαζί στο δίσκο. Εάν δεν έχετε αρκετό δίσκο, τερματίστε με ένα μήνυμα λάθους στο αρχείο καταγραφής.

Το σενάριο πριν τερματίσει πρέπει να καθαρίζει το συμπιεσμένο αρχείο.


Chapter 8. Συγγραφή διαλογικών σεναρίων

Σε αυτό το κεφάλαιο θα συζητήσουμε τη αλληλεπίδραση χρηστών και σεναρίων:

·         Εμφάνιση μηνυμάτων και εξηγήσεων φιλικών προς το χρήστη

·         Λήψη της εισόδου του χρήστη

·         Προτροπή για είσοδο του χρήστη

·         Χρήση περιγραφέων αρχείων για ανάγνωση και εγγραφή σε πολλαπλά αρχεία


8.1. Εμφάνιση μηνυμάτων χρηστών

8.1.1. Διαλογικό ή όχι;

Μερικά σενάρια εκτελούνται χωρίς καμμία αλληλεπίδραση με το χρήστη. Τα πλεονεκτήματα των μη-διαλογικών σεναρίων είναι:

·         Το σενάριο εκτελείται με προβλέψιμο τρόπο κάθε φορά.

·         Το σενάριο μπορεί να εκτελεστεί στο παρασκήνιο.

Όμως, πολλά σενάρια, απαιτούν είσοδο από το χρήστη, ή παρέχουν έξδοδο προς το χρήστη κατά την εκτέλεση. Τα πλεονεκτήματα των διαλογικών σεναρίων, μεταξύ άλλων:

·         Μπορούμε να γράψουμε πιο ευέλικτα σενάρια.

·         Οι χρήστες προσαρμόζουν το σενάριο κατά την εκτέλεσή του με διάφορους τρόπους.

·         Το σενάριο μπορεί να ενημερώνει τη πρόοδο της εκτέλεσής του.

Όταν γράφετε ένα διαλογικό σενάριο μην παραλείπετε τα σχόλια. Ένα σενάιο που εμφανίζειι τα κατάλληλα μηνύματα είναι πολύ πιο φιλικό στο χρήστη και μπορεί πιο εύκολα να διορθωθεί. Ένα σενάριο μπορεί να κάνει τέλεια τη δουλειά του, αλλά  θα δεχτείτε πολλές αιτήσεις για υποστήριξη αν δεν ενημερώνει το χρήστη για το τι κάνει. Γι’αυτό να περιλαμβάνετε μηνύματα που να λένε στο χρήστη να περιμένει για την έξοδο καθώς εκτελείται ένας υπολογισμός. Αν είναι εφικτό, προσπαθείστε να δώσετε μια ένδειξη για το πόσο θα πρέπει να περιμένει ο χρήστης. Εάν η αναμονή θα κρατήσει πολλή ώρα καθώς εκτελείται κάποια εγασία, ίσως πρέπει να σκεφτείτε να περιλάβετε κάποιες ενδείξειςπροόδου της όλης διαδικασίας στην έξοδο του σεναρίου.

Όταν προτρέπετε τον χρήστη να εισάγει δεδομένα, είναι καλύτερο να δίνετε υπερβολικά πολλές πάρα υπερβολικά λίγες πληροφορίες για το είδος των δεδομένων που πρέπει να εισάγει. Αυτό ισχύει και για τον έλεγχο των εκφράσεων καθώς και τα αντίστοιχα μηνύματα χρήσης.

Το Bash έχει τις εντολές echo και printf για να εμφανίζει σχόλια στους χρήστες, και παρόλο που θα έπρεπε να έχετε εξοικειωθεί με τη χρήση της εντολής echo μέχρι τώρα, θα αναφέρουμε και άλλα παραδείγματα στις επομένες ενότητες.


8.1.2. Χρήση της εσωτερικής εντολής echo 

Η εσωτερική εντολή echo εμφανίζει τα ορίσματά της, χωρισμένα με κενά και τελειώνοντας με αλλαγή γραμμής. Η κατάσταση εξόδου είναι πάντα μηδέν. Η εντολή echo έχει μερικές επιλογές:

·         -e: διερμηνεύει τους χαρακτήρες που ακυρώνονται με backslash.

·         -n: ακυρώνει την αλλαγή γραμμής.

Σαν παράδειγμα παράθεσης μηνυμάτων, θα βελτιώσουμε λίγο τα σενάρια feed.sh και penguin.sh από την Ενότητα 7.2.1.2:

 
michel ~/test> cat penguin.sh
#!/bin/bash
 
# This script lets you present different menus to Tux.  He will only be happy
# when given a fish.  To make it more fun, we added a couple more animals.
 
if [ "$menu" == "fish" ]; then
  if [ "$animal" == "penguin" ]; then
    echo -e "Hmmmmmm fish... Tux happy!\n"
  elif [ "$animal" == "dolphin" ]; then
    echo -e "\a\a\aPweetpeettreetppeterdepweet!\a\a\a\n"
  else
    echo -e "*prrrrrrrt*\n"
  fi
else
  if [ "$animal" == "penguin" ]; then
    echo -e "Tux don't like that.  Tux wants fish!\n"
    exit 1
  elif [ "$animal" == "dolphin" ]; then
    echo -e "\a\a\a\a\a\aPweepwishpeeterdepweet!\a\a\a"
    exit 2
  else
    echo -e "Will you read this sign?!  Don't feed the "$animal"s!\n"
    exit 3
  fi
fi
 
michel ~/test> cat feed.sh
#!/bin/bash
# This script acts upon the exit status given by penguin.sh
 
if [ "$#" != "2" ]; then
  echo -e "Usage of the feed script:\t$0 food-on-menu animal-name\n"
  exit 1
else
 
  export menu="$1"
  export animal="$2"
 
  echo -e "Feeding $menu to $animal...\n"
 
  feed="/nethome/anny/testdir/penguin.sh"
 
  $feed $menu $animal
 
result="$?"
 
  echo -e "Done feeding.\n"
 
case "$result" in
 
  1)
    echo -e "Guard: \"You'd better give'm a fish, less they get violent...\"\n"
    ;;
  2)
    echo -e "Guard: \"No wonder they flee our planet...\"\n"
    ;;
  3)
    echo -e "Guard: \"Buy the food that the Zoo provides at the entry, you ***\"\n"
    echo -e "Guard: \"You want to poison them, do you?\"\n"
    ;;
  *)
    echo -e "Guard: \"Don't forget the guide!\"\n"
    ;;
  esac
 
fi
 
echo "Leaving..."
echo -e "\a\a\aThanks for visiting the Zoo, hope to see you again soon!\n"
 
michel ~/test> feed.sh apple camel
Feeding apple to camel...
 
Will you read this sign?!  Don't feed the camels!
 
Done feeding.
 
Guard: "Buy the food that the Zoo provides at the entry, you ***"
 
Guard: "You want to poison them, do you?"
 
Leaving...
Thanks for visiting the Zoo, hope to see you again soon!
 
michel ~/test> feed.sh apple
Usage of the feed script:       ./feed.sh food-on-menu animal-name
 

Λεπτομέρειες για τους χαρακτήρες διαφυγής μπορούν να βρεθούν στην Ενότητα 3.3.2. Ο ακόλουθος πίνακας δίνει μια σύνοψη των ακολουθιών που αναγνωρίζει η εντολή echo:

Πίνακας 8-1. Ακολουθίες διαφυγής στην εντολή echo 

Sequence

Meaning

\a

Alert (bell).

\b

Backspace.

\c

Suppress trailing newline.

\e

Escape.

\f

Form feed.

\n

Newline.

\r

Carriage return.

\t

Horizontal tab.

\v

Vertical tab.

\\

Backslash.

\ONNN

The eight-bit character whose value is the octal value NNN (zero to three octal digits).

\NNN

The eight-bit character whose value is the octal value NNN (one to three octal digits).

\xHH

The eight-bit character whose value is the hexadecimal value (one or two hexadecimal digits).

Για περισσότερες πληροφορίες σχετικά με την εντολή printf και τη χρήση μορφοποιημένης εξόδου, δείτε τις σελίδες πληροφόρησηςη του Bash.


8.2. Λήψη εισόδου χρήστη

8.2.1. Χρήση της εσωτερικής εντολής read 

Η εσωτερική εντολή read είναι η αντίστοιχη των εντολών echo και printf. Η σύνταξη της εντολής read είναι η ακόλουθη:

read [options] NAME1 NAME2 ... NAMEN

Μια γραμμή διαβάζεται από την πρότυπη είσοδο ή από τον περιγραφέα αρχείου που δίνεται ως όρισμα στην επιλογη -u. Η πρώτη λέξη της γραμμής εκχωρείται στο πρώτο όνομα, NAME1, η δεύτερη λέξη στο δεύτερο όνομα, και ούτω καθ’εξής, με τις υπόλοιπόμενες λέξεις και τους διαχωριστές που μεσολαβούν να εκχωρούνται στο τελευταίο όνομα, NAMEN. Αν διαβάζονται από την είσοδο λιγότερες λέξεις από ότι ονόματα, τα υπολοιπόμενα ονόματα εκχωρούνται σαν κενές μεταβλητές.

Οι χαρακτήρες στην τιμή της μεταβλητής IFS χρησιμοποιούνται για να χωρίσουν τη γραμμή εισόδου σε λέξεις και σύμβολα, δείτε Ενότητα 3.4.8. Ο χαρακτήρας backslash μπορεί να χρησιμοποιηθεί για να διαγράψει οποιοδήποτε ιδιαίτερο νόημα για τον επόμενο χαρακτήρα που θα διαβαστεί και για τη συνέχιση γραμμής.

Αν δεν εισαχθούν καθόλου ονόματα, η γραμμή που διαβάζεται, εκχωρείται στη μεταβλητή REPLY.

Ο κώδικας κατάστασης της εντολής read είναι μηδέν, εκτός αν συναντηθεί ένας χαρακτήρας τερματισμού αρχείου, αν το read σταματήσει ή αν ένας άκυρος περιγραφέας αρχείου εισαχθεί σαν όρισμα στην επιλογή -u.

Οι ακόλουθες επιλογές υποστηρίζονται από την εσωτερική εντολή read του Bash:

Πίνακας 8-2. Επιλογές της εσωτερικής εντολής read 

Επιλογή

Σημασία

-a ANAME

Οι λέξεις εκχωρούνται σε διαδοχικές θέσεις της μεταβλητής πίνακα ANAME, ξεκινώντας στο 0. Όλα τα στοιχεία διαγράφονται από την ANAME πριν την εκχώρηση. Άλλα ορίσματα του NAME αγνοούνται.

-d DELIM

Ο πρώτος χαρακτήρας της DELIM χρησιμοποιείται για να τερματίσει την γραμμή εισόδου, αντί της αλλαγής γραμμής.

-e

Η readline χρησιμοποιέιται για την ανάγνωση της γραμμής.

-n NCHARS

Η read επιστρέφει αφού διαβάσει τους χαρακτήρες NCHARS αντί να περιμένει για μια ολοκληρωμένη γραμμή εισόδου.

-p PROMPT

Εμφανίζει την PROMPT, χωρίς αλλαγή γραμμής, πριν δοκιμάσει να διαβάσει οποιαδήποτε είσοδο. Η προτροπή εμφανίζεται μόνο εάν η είσοδος προέρχεται από ένα τερματικό.

-r

Αν δοθεί αυτή η επιλογή, το backslash δεν λειτουργεί σαν χαρακτήρας εξόδου, αλλά λαμβάνεται σαν τμήμα της γραμμής. Συγκεκριμένα, ένα ζευγάρι backslash-newline δεν μπορεί να χρησιμοποιηθεί για τη συνέχιση της γραμμής.

-s

Κατάσταση σιγής. Αν η είσοδος προέρχεται από τερματικό οι χαρακτήρες δεν εμφανίζονται στην οθόνη.

-t TIMEOUT

Η read κάνει χρονομέτρηση και να επιστρέφει σφάλμα αν μια πλήρης γραμμή εισόδου δεν διαβαστεί μέσα στα δευτερόλεπτα που ορίζονται στο TIMEOUT. Αυτή η επιλογή δεν έχει κανένα αποτέλεσμα αν η read δεν διαβάζει είσοδο από τερματικό ή σωλήνωση.

-u FD

Ανάγνωση εισόδου από τον περιγραφέα αρχείου FD.

Ακολουθεί ένα απλό παράδειγμα, που βελτιώνει το σενάριο leaptest.sh από το προηγούμενο κεφάλαιο:

 
michel ~/test> cat leaptest.sh
#!/bin/bash
# This script will test if you have given a leap year or not.
 
echo "Type the year that you want to check (4 digits), followed by [ENTER]:"
 
read year
 
if (( ("$year" % 400) == "0" )) || (( ("$year" % 4 == "0") && ("$year" % 100 !=
"0") )); then
  echo "$year is a leap year."
else
  echo "This is not a leap year."
fi
 
michel ~/test> leaptest.sh
Type the year that you want to check (4 digits), followed by [ENTER]:
2000
2000 is a leap year.

8.2.2. Προτροπή για είσοδο χρήστη

Το επόμενο παράδειγμα δείχνει τη χρήση προτροπών για να δωθούν οδηγίες στο χρήστη για την είσοδο που απαιτείται:

 
michel ~/test> cat friends.sh
#!/bin/bash
 
# This is a program that keeps your address book up to date.
 
friends="/var/tmp/michel/friends"
 
echo "Hello, "$USER".  This script will register you in Michel's friends database."
 
echo -n "Enter your name and press [ENTER]: "
read name
echo -n "Enter your gender and press [ENTER]: "
read -n 1 gender
echo
 
grep -i "$name" "$friends"
 
if  [ $? == 0 ]; then
  echo "You are already registered, quitting."
  exit 1
elif [ "$gender" == "m" ]; then
  echo "You are added to Michel's friends list."
  exit 1
else
  echo -n "How old are you? "
  read age
  if [ $age -lt 25 ]; then
    echo -n "Which colour of hair do you have? "
    read colour
    echo "$name $age $colour" >> "$friends" 
    echo "You are added to Michel's friends list.  Thank you so much!"
  else
    echo "You are added to Michel's friends list."
    exit 1
  fi
fi
 
michel ~/test> cp friends.sh /var/tmp; cd /var/tmp
 
michel ~/test> touch friends; chmod a+w friends
 
michel ~/test> friends.sh
Hello, michel.  This script will register you in Michel's friends database.
Enter your name and press [ENTER]: michel
Enter your gender and press [ENTER] :m
You are added to Michel's friends list.
 
michel ~/test> cat friends
 

Σημειώστε οτι εδώ δεν παραλείπεται καμμία έξοδος. Το σενάριο απλά αποθηκεύει πληροφορία σχετικά με τα πρόσωπα για τα οποία ενδιαφέρεται η Michel, και πάντα ανακοινώνει τη πρόσθεσή σας στη λίστα, εκτός και αν είστε ήδη εκεί.

Άλλα πρόσωπα μπορούν τώρα να εκτελέσουν το σενάριο:

 
[anny@octarine tmp]$ friends.sh
Hello, anny.  This script will register you in Michel's friends database.
Enter your name and press [ENTER]: anny
Enter your gender and press [ENTER] :f
How old are you? 22
Which colour of hair do you have? black
You are added to Michel's friends list.

Μετά από λίγο, η λίστα friends αρχίζει να μοιάζει κάπως έτσι:

 
tille 24 black
anny 22 black
katya 22 blonde
maria 21 black
--output omitted--

Βέβαια, η κατάσταση δεν είναι ιδεώδης, αφού ο καθένας μπορεί να τροποποιήσει (αλλά όχι να διαγράψει) το αρχείο της Michel. Μπορείτε να λύσετε αυτό το πρόβλημα με τη χρήση ειδικών μεθόδων πρόσβασης στο αρχείο σεναρίου, δείτε τα SUID και SGID στο εγχειρίδιο Εισαγωγής στο Linux.


8.2.3. Ανακατεύθυνση και περιγραφείς αρχείων

8.2.3.1. Γενικά

Καθώς γνωρίζετε από τη χρήση του βασικού φλοιού, η είσοδος και η έξοδος μιας εντολής μπορούν να ανακατευθυνθούν πριν αυτή εκτελεστεί, χρησιμοποιώντας μια ειδική σήμανση-τον τελεστή ανακατεύθυνσης-που δειρμηνεύεται από το φλοιό. Η ανακατεύθυνση μπορεί επίσης να χρησιμοποιηθεί για να ανοίξει και να κλείσει αρχεία για το τρέχον περιβάλλον εκτέλεσης του φλοιού.

Η ανακατεύθυνση μπορεί επίσης να βρεθεί σε ένα σενάριο, έτσι ώστε να δεχτεί είσοδο από κάποιο αρχείο, για παράδειγμα, ή για να στείλει έξοδο σε κάποιο αρχείο. Αργότερα, ο χρήστης μπορεί να μελετήσει το αρχείο εξόδου ή το αρχείο μπορεί αυτό να χρησιμοποιηθεί από άλλο σενάριο σαν είσοδος.

Οι είσοδοι και οι έξοδοι ενός αρχείου συνδεόονται με ακέραιους αριθμούς (χειριστές)  που αντιστοιχούν τα ανοικτά αρχεία μαις διεργασίας. Αυτές οι αριθμητικές τιμές είναι γνωστές σαν περιγραφείς αρχείων. Οι πιο γνωστοί περιγραφείς αρχείων είναι η πρότυπη είσοδος, έξοδος και σφάλμα (stdin, stdout και stderr), με περιγραφείς αρχείων τους αριθμούς 0, 1 και 2, αντίστοιχα. Αυτοί οι αριθμοί και οι αντίστοιχές τους συσκευές είναι δεσμευμένοι. Το Bash μπορεί επίσης να λάβει ως περιγραφείς αρχείου τις θύρες TCP ή UDP δικτυωμένων διακομιστών.

Η παρακάτω έξοδος δείχνει πως οι περιγραφείς αρχείου δείχνουν σε υπάρχουσες συσκευές:

 
michel ~> ls -l /dev/std*
lrwxrwxrwx  1 root    root     17 Oct  2 07:46 /dev/stderr -> ../proc/self/fd/2
lrwxrwxrwx  1 root    root     17 Oct  2 07:46 /dev/stdin -> ../proc/self/fd/0
lrwxrwxrwx  1 root    root     17 Oct  2 07:46 /dev/stdout -> ../proc/self/fd/1
 
michel ~> ls -l /proc/self/fd/[0-2]
lrwx------  1 michel  michel   64 Jan 23 12:11 /proc/self/fd/0 -> /dev/pts/6
lrwx------  1 michel  michel   64 Jan 23 12:11 /proc/self/fd/1 -> /dev/pts/6
lrwx------  1 michel  michel   64 Jan 23 12:11 /proc/self/fd/2 -> /dev/pts/6

Ίσως θέλετε να ελέγξετε το info MAKEDEV και το info proc για περισσότερες πληροφορίες για το /proc και για τον τρόπο που το σύστημα χειρίζεται τους περιγραφείς αρχείου για κάθε τρέχουσα διαδικασία.

Καθώς εκτελείτε ένα σενάριο από την γραμμή εντολών, τίποτα δεν θα αλλάξει ιδιαίτερα διότι η θυγατρική διεργασία φλοιού θα χρησιμοποιήσει τους ίδιους περιγραφείς αρχείων με τον γονέα. Όταν κανένας γονέας δεν είναι διαθέσιμος, για παράδειγμα όταν εκτελείτε ένα σενάριο χρησιμοποιώντας την υπηρεσία cron , οι βασικοί περιγραφείς αρχείου είναι σωληνώσεις ή άλλα (προσωρινά) αρχεία, εκτός αν χρησιμοποιήθηκε κάποια ανακατεύθυνση. Αυτό αποδεικνύεται στο παρακάτω παράδειγμα, το οποίο δείχνει την έξοδο από ένα απλό σενάριο at:

 
michel ~> date
Fri Jan 24 11:05:50 CET 2003
 
michel ~> at 1107
warning: commands will be executed using (in order) 
a) $SHELL b) login shell c)/bin/sh
at> ls -l /proc/self/fd/ > /var/tmp/fdtest.at
at> <EOT>
job 10 at 2003-01-24 11:07
 
michel ~> cat /var/tmp/fdtest.at
total 0
lr-x------    1 michel michel  64 Jan 24 11:07 0 -> /var/spool/at/!0000c010959eb (deleted)
l-wx------    1 michel michel  64 Jan 24 11:07 1 -> /var/tmp/fdtest.at
l-wx------    1 michel michel  64 Jan 24 11:07 2 -> /var/spool/at/spool/a0000c010959eb
lr-x------    1 michel michel  64 Jan 24 11:07 3 -> /proc/21949/fd

Και ένα με cron:

 
michel ~> crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.21968 installed on Fri Jan 24 11:30:41 2003)
# (Cron version -- $Id: chap8.xml,v 1.8 2005/09/05 12:39:22 tille Exp $)
32 11 * * * ls -l /proc/self/fd/ > /var/tmp/fdtest.cron
 
michel ~> cat /var/tmp/fdtest.cron
total 0
lr-x------    1 michel michel  64 Jan 24 11:32 0 -> pipe:[124440]
l-wx------    1 michel michel  64 Jan 24 11:32 1 -> /var/tmp/fdtest.cron
l-wx------    1 michel michel  64 Jan 24 11:32 2 -> pipe:[124441]
lr-x------    1 michel michel  64 Jan 24 11:32 3 -> /proc/21974/fd

8.2.3.2. Ανακατεύθυνση σφαλμάτων

Από τα προηγούμενα παραδείγματα, είναι ξεκάθαρο ότι μπορείτε να παρέχετε αρχεία εισόδου και εξόδου για ένα σενάριο (δείτε Ενότητα 8.2.4 για περισσότερα), αλλά κάποιοι ξεχνούν να ανακατευθύνουν τα λάθη – εξόδους που μπορεί αργότερα να φανούν χρήσιμες. Επίσης, αν είστε τυχεροί, τα σφάλματα θα σας σταλούν με mail και ενδεχομένως ο λόγος της αποτυχίας να αποκαλυφθεί. Αν δεν  είστε τόσο τυχεροί, τα λάθη θα οδηγήσουν το σενάριο σε αποτυχία που δεν θα συλληφθεί και δεν θα σταλθεί πουθενά, έτσι ώστε δεν θα μπορέσετε να εκτελέσετε μια αξόλογη εκσφαλμάτωση.

Κατά την ανακατεύθυνση των σφαλμάτων, σημειώνεται ότι η σειρά παρουσίασης είναι σημαντική. Για παράδειγμα, αυτή η εντολή, εισηγμένη στο  /var/spool

 
ls -l * 2 > /var/tmp/unaccessible-in-spool

θα ανακατευθύνει την έξοδο της εντολής ls στο αρχείο unaccessible-in-spool στο /var/tmp. Η εντολή

 
ls -l * > /var/tmp/spoollist 2 >& 1

θα κατευθύνει τόσο τη πρότυπη είσοδο όσο και το πρότυπο σφάλμα στο αρχείο spoollist. Η εντολή

 
ls -l * 2 >& 1 > /var/tmp/spoollist

κατευθύνει μόνο τη πρότυπη έξοδο στο αρχείο, διότι το πρότυπο σφάλμα αντιγράφεται στη πρότυπη έξοδο πριν την ανακατεύθυνση της πρότυπης εξόδου.

Για ευκολία, τα σφάλματα συχνά ανακατευθύνονται στο /dev/null, αν είναι βέβαιο ότι δεν θα χρειαστούν. Εκατοντάδες παραδείγματα μπορούν να βρεθούν στα σενάρια εκκίνησης για το σύστημά σας.

Το Bash επιτρέπει στη πρότυπη έξοδο και το πρότυπο σφάλμα να κατευθύνονται μαζί στο αρχείο στο αρχείο του οποίου το όνομα είναι το αποτέλεσμα της επέκτασης του FILE με αυτή τη δομή:

&> FILE

Αυτό είναι το αντίστοιχο του > FILE 2>&1που χρησιμοποιηθηκε στο προηγούμενο σύνολο παραδειγμάτων. Συνδέεται επίσης συχνά με την ανακατεύθυνση στο /dev/null, για παράδειγμα όταν θέλετε μια εντολή να εκτελεστεί, χωρίς να σας ενδιαφέρει τι έξοδο ή σφάλματα θα δώσει.


8.2.4. Είσοδος και έξοδος αρχείων

8.2.4.1. Χρήση /dev/fd

Ο κατάλογος /dev/fd περιέχει στοιχεία με ονόματα 0, 1, 2, και ούτω καθεξής. Το άνοιγμα του αρχείου /dev/fd/N ισοδυναμεί το να αντιγραφή τον περιγραφέα αρχείου NΑν το σύστημα σας [παρέχει τα  /dev/stdin, /dev/stdout και /dev/stderr, θα δείτε ότι αυτά είναι ίδια με τα /dev/fd/0, /dev/fd/1 και /dev/fd/2, αντίστοιχα.

Η κύρια χρήση των αρχείων /dev/fd είναι από το φλοιό. Αυτός ο μηχανισμός επιτρέπει σε προγράμματα που χρησιμοποιούν ως ορίσματα ονόματα καταλόγων, να χειρίζονται τη πρότυπη είσοδο και έξοδο με τον ίδιο τρόπο που χειρίζονται και τα άλλα ονόματα καταλόγων. Αν το /dev/fd δεν είναι διαθέσιμο στο σύστημα, θα πρέπει να βρείτε ένα τρόπο να παρακάμψτετε το πρόβλημα. Αυτό μπορεί να γίνει, για παράδειγμα, χρησιμοποιώντας την παύλα (-) για να υποδείξεις ότι τι πρόγραμμα πρέπει να διαβάζει από μια σωλήνωση. Παράδειγμα:

 
michel ~> filter body.txt.gz | cat header.txt - footer.txt
This text is printed at the beginning of each print job and thanks the sysadmin
for setting us up such a great printing infrastructure.
 
Text to be filtered.
 
This text is printed at the end of each print job.

Η εντολή cat πρώτα διαβάζει το αρχείο header.txt, μετά την πρότυπη είσοδλο του, η οποία είναι η έξοδος της εντολής filter, και τελευταίο το αρχείο footer.txt. Το ιδιαίτερο νόημα της παύλας σαν όρισμα της γραμμής εντολών που αναφέρεται στη πρότυπη είσοδο ή έξοδο είναι μια παρανόηση ότι πέρασε σε πολλά προγράμματα. Επίσης μπορεί να υπάρξουν προβλήματα στον καθορισμό της παύλας ως πρώτο όρισμα, καθώς μπορεί να μεταφραστεί ως μια επιλογή στην προηγούμενη εντολή. Χρησιμοποιώντας το /dev/fd επιτρέπεται η ομοιομορφία και αποτρέπονται οι συγχύσεις:

 
michel ~> filter body.txt | cat header.txt /dev/fd/0 footer.txt | lp

Σε αυτό το καθαρό παράδειγμα, κλαθε έξοδος επιπρόσθετα στέλνεται μέσω σωλήνωσης μέσω lp στο προεπιλεγμένο εκτυπωτή.


8.2.4.2. Read και exec

8.2.4.2.1. Εκχώρηση περιγραφέων αρχείων σε αρχεία

Άλλος ένας τρόπος για να δείτε τους περιγραφείς αρχείων είναι να τους φαντάζεστε σαν ένα τρόπο εκχώρησης μιας αριθμητικής τιμής σένα αρχείο. Αντί για τη χρήση του ονόματος του αρχείου, μπορείτε να χρησιμοποιήσετε τον αριθμό του περιγραφέα αρχείου. Η εσωτερική εντολή exec χρησιμοποιείται ώστε να εκχώρησει ένα περιγραφέα αρχείου σε ένα αρχείο. Χρησιμοποιείστε

exec fdN> file

για εκχώρηση του περιγραφέα αρχείου N στο αρχείο για έξοδο, και

exec fdN< file

για εκχώρηση του περιγραφέα αρχείου N στο αρχείο για είσοδο. Αφού ένας περιγραφέας αρχείου εκχωρήθηκε  σε ένα αρχείο, μπορεί να χρησιμοποιηθεί με τους χειριστές ανακατεύθυνσης του φλοιού, όπως αποδεικνύεται στο ακόλουθο παράδειγμα:

 
michel ~> exec 4 > result.txt
 
michel ~> filter body.txt | cat header.txt /dev/fd/0 footer.txt >& 4
 
michel ~> cat result.txt
This text is printed at the beginning of each print job and thanks the sysadmin
for setting us up such a great printing infrastructure.
 
Text to be filtered.
 
This text is printed at the end of each print job.

 

Note

Περιγραφέας αρχείου 5

 

Η χρήση του συγκεκριμένου περιγραφέα αρχείου μπορεί να προκαλέσει προβλήματα, δείτε το Advanced Bash-Scripting Guide, κεφάλαιο 16. Συνιστάται έντονα να απογεύγετε τη χρήση του.


8.2.4.2.2. Ανάγνωση σε σενάρια

Το ακόλουθο παράδειγμα δείχνει πως μπορείτε να εναλλάσετε είσοδο από αρχείο και από γραμμή εντολών:

 
michel ~/testdir> cat sysnotes.sh
#!/bin/bash
 
# This script makes an index of important config files, puts them together in
# a backup file and allows for adding comment for each file.
 
CONFIG=/var/tmp/sysconfig.out
rm "$CONFIG" 2>/dev/null
 
echo "Output will be saved in $CONFIG."
 
exec 7<&0
 
exec < /etc/passwd
 
# Read the first line of /etc/passwd
read rootpasswd
 
echo "Saving root account info..."
echo "Your root account info:" >> "$CONFIG"
echo $rootpasswd >> "$CONFIG"
 
exec 0<&7 7<&-
 
echo -n "Enter comment or [ENTER] for no comment: "
read comment; echo $comment >> "$CONFIG"
 
echo "Saving hosts information..."
 
# first prepare a hosts file not containing any comments
TEMP="/var/tmp/hosts.tmp"
cat /etc/hosts | grep -v "^#" > "$TEMP"
 
exec 7<&0
exec < "$TEMP"
 
read ip1 name1 alias1
read ip2 name2 alias2
 
echo "Your local host configuration:" >> "$CONFIG"
 
echo "$ip1 $name1 $alias1" >> "$CONFIG"
echo "$ip2 $name2 $alias2" >> "$CONFIG"
 
exec 0<&7 7<&-
 
echo -n "Enter comment or [ENTER] for no comment: "
read comment; echo $comment >> "$CONFIG"
rm "$TEMP"
 
michel ~/testdir> sysnotes.sh
Output will be saved in /var/tmp/sysconfig.out.
Saving root account info...
Enter comment or [ENTER] for no comment: hint for password: blue lagoon
Saving hosts information...
Enter comment or [ENTER] for no comment: in central DNS
 
michel ~/testdir> cat /var/tmp/sysconfig.out
Your root account info:
root:x:0:0:root:/root:/bin/bash
hint for password: blue lagoon
Your local host configuration:
127.0.0.1 localhost.localdomain localhost
192.168.42.1 tintagel.kingarthur.com tintagel
in central DNS

8.2.4.3. Κλείσιμο περιγραφέων αρχείων

Καθώς η θυγατρική διεργασία κληρονομεί ανοικτούς περιγραφείς αρχείου, είναι μια καλή πρακτική να κλείνετε ένα περιγραφέα αρχείου όταν δεν είναι πλέον χρήσιμος. Αυτό γίνεται χρησιμοποιώντας την σύνταξη

exec fd<&-

Στο παραπάνω παράδειγμα, ο περιγραφέας αρχείου 7, ο οποίος εκχωρήθηκε σε πρότυπη είσοδο, κλείνει κάθε φορά που ο χρήστης χρειάζεται να έχει πρόσβαση στην πραγματική συσκευή πρότυπης εισόδου, συνήθως το πληκτρολόγιο.

Το ακόλουθο είναι ένα απλό παράδειγμα ανακατεύθυνσης μόνο του πρότυπου σφάλματος σε σωλήνα:

 
michel ~> cat listdirs.sh
#!/bin/bash
 
# This script prints standard output unchanged, while standard error is 
# redirected for processing by awk.
 
INPUTDIR="$1"
 
exec 6>&1
 
ls "$INPUTDIR"/* 2>&1 >&6 6>&- \
                               # Closes fd 6 for awk, but not for ls.
 
| awk 'BEGIN { FS=":" } { print "YOU HAVE NO ACCESS TO" $2 }' 6>&-
 
exec 6>&-

8.2.4.4. Ηere documents

Συχνά, το σενάριό σας μπορεί να καλέσει άλλο πρόγραμμα ή σενάριο που απαιτεί είσοδο. Τα here documnets παρέχουν μια μέθοδο καθοδήγησης του φλοιού ώστε να διαβάζει δεδομένα από την τρέχουσα είσοδο μέχρι να βρεθεί μια γραμμή που να περιέχει τη συμβολοσειρά που αναζητούμε . Όλες οι  γραμμές που διαβάστηκαν μέχρι εκείνο το σημείο, χρησιμοποιούνται σαν πρότυπη είσοδος για μια εντολή.

Αποτέλεσμα είναι να μην χρειάζεται να καλέσετε ξεχωριστά αρχεία. Μπορείτε να χρησιμοποιήσετε ειδικούς χαρακτήρες φλοιού, και φαίνεται καλύτερο από μια δέσμη εντολών echo:

 
michel ~> cat startsurf.sh
#!/bin/bash
 
# This script provides an easy way for users to choose between browsers.
 
echo "These are the web browsers on this system:"
 
# Start here document
cat << BROWSERS
mozilla
links
lynx
konqueror
opera
netscape
BROWSERS
# End here document
 
echo -n "Which is your favorite? "
read browser
 
echo "Starting $browser, please wait..."
$browser &
 
michel ~> startsurf.sh
These are the web browsers on this system:
mozilla
links
lynx
konqueror
opera
netscape
Which is your favorite? opera
Starting opera, please wait...

Αν και μιλούμε για ένα here document, στην ουσία είναι μια δομή μέσα στο ίδιο σενάριο. Αυτό είναι ένα παράδειγμα αυτόματης εγκατάστασης πακέτου, αν και κανονικά θα έπρεπε να εισάγουμε μια επιβεβαίωση:

 
#!/bin/bash
 
# This script installs packages automatically, using yum.
 
if [ $# -lt 1 ]; then
        echo "Usage: $0 package."
        exit 1
fi
 
yum install $1 << CONFIRM
y
CONFIRM

Και έτσι εκτελείται το σενάριο. Όταν προτρέπεται για είσοδο με το μήνυμα "Is this ok [y/N]", το σενάριο απαντά αυτόματα "y":

 
[root@picon bin]# ./install.sh tuxracer
Gathering header information file(s) from server(s)
Server: Fedora Linux 2 - i386 - core
Server: Fedora Linux 2 - i386 - freshrpms
Server: JPackage 1.5 for Fedora Core 2
Server: JPackage 1.5, generic
Server: Fedora Linux 2 - i386 - updates
Finding updated packages
Downloading needed headers
Resolving dependencies
Dependencies resolved
I will do the following:
[install: tuxracer 0.61-26.i386]
Is this ok [y/N]: EnterDownloading Packages
Running test transaction:
Test transaction complete, Success!
tuxracer 100 % done 1/1
Installed:  tuxracer 0.61-26.i386
Transaction(s) Complete

8.3. Περίληψη

Σε αυτό το κεφάλαιο, μάθαμε πως να παρέχουμε μηνύματα και σχόλια στον χρήστη και πώς να προτρέπουμε τον χρήστη για είσοδο. Αυτό γίνεται συνήθως χρησιμοποιώντας τον συνδυασμό echo/read. Επίσης συζητήσαμε για το πώς μπορούν να χρησιμοποιηθούν τα αρχεία σαν είσοδοι και έξοδοι χρησιμοποιώντας τους περιγραφείς αρχείων και την ανακατεύθυνση, και πως αυτό μπορεί να συνδυαστεί με την λήψη εισόδων από τον χρήστη.

Τονίσαμε την σημασία του να παρέχουμε επαρκή μηνύματα στους χρήστες των σεναρίων μας. Όπως πάντα, όταν άλλοι χρησιμοποιούν το σενάριό μας, είναι καλύτερα να δίνετε πάρα πολλές πληροφορίες παρά ανεπαρκείς πληροφορίες. Τα here documnets είναι ένας τύπος δομής φλοιού που επιτρέπει την δημιουργία λιστών, που παρέχουν επιλογές στους χρήστες. Αυτή η δομή μπορεί επίσης να χρησιμοποιηθεί για να εκτελέσει διαλογικές εργασίες στο παρασκήνιο, χωρίς αλληλεπίδραση.


8.4. Ασκήσεις

Οι ασκήσεις είναι πρακτικές εφαρμογές των δομών που συζητήθηκαν σε αυτό το κεφάλαιο. Καθώς γράφετε τα σενάρια μπορείτε να τα ελέγχετε χρησιμοποιώντας έναν κατάλογο ελέγχου που δεν περιέχει πολλά δεδομένα. Γράψτε και ελέγξτε  κάθε βήμα ξεχωριστά, μη προσπαθήσετε να γράψετε ολόκληρο το σενάριο με τη μια.

1.      Γράψτε ένα σενάριο που να ζητά την ηλικία του χρήστη. Αν είναι ίση ή μεγαλύτερη των 16, το σενάριο να εμφανίζειι ένα μήνυμα που να λέει ότι αυτός ο χρήστης δικαιούται να καταναλώσει αλκοόλ. Αν η ηλικία του είναι κάτω των 16, να εμφανίζει ένα μήνυμα που να λέει στο χρήστη σε πόσα χρόνια θα δικαιούται να καταναλώσει νόμιμα αλκοόλ.

Επιπλέον, υπολογίστε πόση μπύρα ήπιε (κατά μέσο όρο) συνολικά ένας χρήστης 18+ (100 λίτρα/έτος) και εμφάνισε αυτή την πληροφορία για τον χρήστη.

.2.      Γράψτε ένα script που να παίρνει σαν όρισμα ένα αρχείο. Χρησιμοποιείστε ένα here document που να παρουσιάζει στον χρήστη επιλογές για συμπίεση του αρχείου. Πιθανές επιλογές μπορεί να είναι gzip, bzip2, compress και zip

3.      Γράψτε ένα σενάριο που να ονομάζεται homebackup που να αυτοματοποιεί το tar ώστε το πρόσωπο που εκτελεί το σενάριο να χρησιμοποιεί συγκεκριμένες επιλογές (cvp) και σταθερό κατάλογο προορισμού (/var/backups) για να κάνει αντίγραφα του οικείου καταλόγου. Εφαρμόστε τα ακόλουθα:

o        Ελέγξτε για τον αριθμό των ορισμάτων. Το σενάριο πρέπει να εκτελείται χωρίς ορίσματα. Αν παρουσιαστούν ορίσματατο σενάριο εμφανίζει κάποιο μήνυμα και τερματίζει..

o        Καθορίστε, αν κατάλογος backups έχει αρκετό ελεύθερο χώρο για να χωρέσει το αντίγραφο.

o        Ρωτήστε τον χρήστη αν επιθυμεί ένα πλήρες ή ένα αυξητικό αντίγραφο. Αν ο χρήστης δεν έχει ακόμα  ένα πλήρες αντίγραφο, τυπώστε ένα μήνυμα ότι θα ληφθεί ένα πλήρες αντίγραφο. Στην περίπτωση ενός αυξητικού αντιγράφου, να γίνει μόνο αν το πλήρες αντίγραφο είναι παλαιότερο από μια εβδομάδα.

o        Συμπιέστε το αντίγραφο χρησιμοποιώντας οποιοδήποτε εργαλείο συμπίεσης. Πληροφορήστε τον χρήστη ότι το σενάριο το κάνει αυτό επειδή μπορεί να πάρει κάποιο χρόνο, κατά τον οποίο ο χρήστης μπορεί να ανησυχήσει ότι δεν εμφανίζεται κάποια έξοδος στην οθόνη.

o        Εμφανίστε ένα μήνυμα που να ενημερώνει τον χρήστη για το μέγεθος του συμπιεσμένου αντιγράφου.

Δείτε το info tar ή την Εισαγωγή στο Linux, κεφάλαιο 9, .

4.      Γράψτε ένα σενάριο που να ονομάζεται simple-useradd.sh το οποίο θα προσθέτει έναν τοπικό χρήστη στ σύστημα. Αυτό το σενάριο πρέπει:

o        Να δέχεται μόνο ένα όρισμα ή αλλιώς να τερματίζει αφού εμφανίσει ένα ενημερωτικό μήνυμα..

o        Να ελέγχει το /etc/passwd και να καθορίζει το πρώτο ελεύθερο ID χρήστη. Να εμφανίζει ένα μήνυμα που να περιέχει αυτό το ID.

o        Να δημιουργεί μια προσωπική ομάδα γι’αυτόν τον χρήστη, ελέγχοντας το αρχείο /etc/group. Να εμφανίζει ένα μήνυμα που να περιέχει το ID της ομάδας.

o        Να συλλέγει πληροφορίες από τον χρήστη: ένα σχόλιο που να περιγράφει τον νέο χρήστη, επιλογή από λίστα  φλοιών  (έλεγχος για δυνατότητα αποδοχής, αλλιώς έξοδος με εμφάνιση ενός μηνύματος), ημερομηνία λήξης του λογαριασμού, επιπλέον ομάδες στις οποίες ο καινούργιος χρήστης θα είναι μέλος.

o        Με την πληροφορία που συλλέχθηκε, να προσθέτει μια γραμμή στα /etc/passwd, /etc/group και /etc/shadow, να δημιουργεί τον οικείο κατάλογο του χρήστη (με σωστές άδειες!), να προσθέτει τον χρήστη στις υπόλοιπες ομάδες που επιθυμεί.

o        Να θέτει τον κωδικό πρόσβασης γι’αυτόν τον χρήστη σε ένα προκαθορισμένο γνωστό αλφαριθμητικό.

5.      Γράψτε ξανά το σενάριο από την Ενότητα 7.2.1.4 έτσι ώστε να δέχεται είσοδο από τον χρήστη αντί να την λαμβάνει από την πρώτο όρισμα.


Κεφάλαιο 9. Επαναληπτικές εργασίες

Με την ολοκλήρωση αυτού του κεφαλαίου, θα είστε έτοιμοι να

·         Χρησιμοποιήσετε τους βρόχους for, while και until , και να αποφασίσετε ποιος βρόχος είναι κατάλληλος για κάθε περίπτωση 

·         Χρησιμοποιήσετε τις εσωτερικές εντολές του Bah break και continue.

·         Γράψετε σενάρια χρησιμοποιώντας τη δήλωση select.

·         Γράψετε σενάρια που δέχονται μεταβλητό αριθμό ορισμάτων.


9.1. Ο βρόχος for 

9.1.1. Πώς δουλεύει;

Ο βρόχος for είναι ο πρώτος από τις τρεις δομές  επανάληψης του φλοιού . Αυτός ο βρόχος επιτρέπει τον ορισμό μιας λίστας τιμών. Ένα σύνολο από εντολές εκτελείται για κάθε τιμή της λίστας

Η σύνταξη αυτού του βρόγχου είναι:

for NAME [in LIST ]; do COMMANDS; done

Αν το [in LIST ]; δεν υπάρχει αντικαθίσταται με in $@ και ο βρόχος for εκτελεί τις εντολές μια φορά για κάθε παράμετρο θέσης που έχει οριστεί (δείτε Ενότητα 3.2.5 και Ενότητα 7.2.1.2).

Η κατάσταση επιστροφής είναι η κατάσταση εξόδου της τελευταίας εντολής που εκτελείται Αν δεν εκτελεστεί καμία εντολή επειδή η LIST δεν επεκτείνεται σε κάποιο στοιχείο, η κατάσταση επιστροφής είναι μηδέν.

Το NAME μπορεί να είναι το όνομα οποιασδήποτε μεταβλητής, παρόλο που συνήθως χρησιμοποιείται το i Η LIST μπορεί να είναι οποιαδήποτε λίστα που περιέχει λέξεις, αλφαριθμητικά ή αριθμούς, και μπορεί να είναι σταθερά ή να προέρχονται από την εκτέλεση κάποιας εντολής. Οι COMMANDS, οι προς εκτέλεση εντολές, μπορεί επίσης να είναι οποιεςδήποτε εντολές του λειτουργικού συστήματος, σενάρια, προγράμματα ή δηλώσεις φλοιών. Στην πρώτη εκτέλεση του βρόχου, το  NAME παίρνει τη τιμή του πρώτου στοιχείου της λίστας. Στη δεύτερη εκτέλεση, η τιμή του τίθεται ως το δεύτερο στοιχείο της λίστας, κ.ο.κ. Ο βρόχος ολοκληρώνεται όταν το NAME λάβει κάθε μια από τις τιμές της LIST..


9.1.2. Παραδείγματα

9.1.2.1. Χρήση της αντικατάστασης εντολών για τον καθορισμό των στοιχείων LIST

Το πρώτο παράδειγμα είναι από τη γραμμή εντολών και δείχνει τη χρήση ενός βρόχου for που αντιγράφει κάθε αρχείο με κατάληξη .xml σε ένα αρχείο με κατάληξη .bak. Μετά την εισαγωγή της εντολής, μπορείτε να εργασθείτε στα πρωτότυπα αρχεία με ασφάλεια:

 
[carol@octarine ~/articles] ls *.xml
file1.xml  file2.xml  file3.xml
 
[carol@octarine ~/articles] ls *.xml > list
 
[carol@octarine ~/articles] for i in `cat list`; do cp "$i" "$i".bak ; done
 
[carol@octarine ~/articles] ls *.xml*
file1.xml  file1.xml.bak  file2.xml  file2.xml.bak  file3.xml  file3.xml.bak

Αυτό το παράδειγμα εμφανίζει τα αρχεία στο /sbin που είναι απλά αρχεία, πιθανώς σενάρια:

 
for i in `ls /sbin`; do file /sbin/$i | grep ASCII; done

9.1.2.2. Χρήση του περιεχομένου μιας μεταβλητής για τον καθορισμό των στοιχείων LIST

Η παρακάτω εφαρμογή είναι ένα σενάριο μετατροπής αρχείων HTML, συμβατών με συγκεριμένο σχήμα, σε αρχεία PHP. Η μετατροπή γίνεται με την αφαίρεση των πρώτων 25 και των τελευταίων 21 γραμμών, αντικαθιστώντας τις με δύο επιθέματα PHP που παρέχουν γραμμές κεφαλής και τερματισμού: 

 
[carol@octarine ~/html] cat html2php.sh
#!/bin/bash
# specific conversion script for my html files to php
LIST="$(ls *.html)"
for i in "$LIST"; do
     NEWNAME=$(ls "$i" | sed -e 's/html/php/')
     cat beginfile > "$NEWNAME"
     cat "$i" | sed -e '1,25d' | tac | sed -e '1,21d'| tac >> "$NEWNAME"
     cat endfile >> "$NEWNAME"
done

Αφού δεν έχουμε αρίθμηση γραμμών, δεν υπάρχει τρόπος να αρχίσουμε τις διαγραφές των τελευταίων γραμμών πριν φθάσουμε στο τέλος του αρχείου, Το πρόβλημα λύνεται με τη χρήση της εντολής tac, που αντιστρέφει τις γραμμές ενός αρχείου.


9.2. Ο βρόχος while

9.2.1. Τι είναι;

Η δομή while επιτρέπει επαναληπτική εκτέλεση μιας λίστας εντολών, όσο η εντολή που ελέγχει το βρόχο while εκτελείται με επιτυχία (κατάσταση εξόδου μηδέν). Η σύνταξη είναι

while CONTROL-COMMAND; do CONSEQUENT-COMMANDS; done

Η CONTROL-COMMAND μπορεί να είναι οποιαδήποτε εντολή (ή εντολές) που μπορούν να τερματίσουν επιστρέφοντας κατάσταση επιτυχίας ή αποτυχίας. Οι CONSEQUENT-COMMANDS μπορεί να είναι εντολές, πρόγραμμα, σενάριο ή δομή φλοιού.

Μόλις η CONTROL-COMMAND αποτύχει, ο βρόχος τερματίζει. Σε ένα σενάριο, η εκτέλεση συνεχίζεται από την εντολή που ακολουθεί τη δήλωση done.

Η κατάσταση εξόδου της δομής είναι είτε αυτή της τελευταία εντολής από τις CONSEQUENT-COMMANDS, ή μηδέν αν καμμία εντολή δεν εκτελεστεί.


9.2.2. Παραδείγματα

9.2.2.1. Απλό παράδειγμα με while

Να ένα παράδειγμα για τον ανυπόμονο:

#!/bin/bash
 
# This script opens 4 terminal windows.
 
i="0"
 
while [ $i -lt 4 ]
do
xterm &
i=$[$i+1]
done

9.2.2.2. Ένθετοι βρόχοι while

Το παράδειγμα που ακολουθεί αντιγράφει εικόνες από μια on-line webcam σετά  ένα κατάλογο ιστοχώρου. Κάθε πέντε λεπτά λαμβάνεται μια εικόνα. Κάθε ώρα, δημιουργείται ένας νέος κατάλογος, που κρατά τις εικόνες εκείνης της ώρας. Κάθε μέρα δημιουργείται ένας κατάλογος που περιέχει 24 υποκαταλόγους. Το σενάριο εκτελείται στο παρασκήνιο.

 
#!/bin/bash
 
# This script copies files from my homedirectory into the webserver directory.
# (use scp and SSH keys for a remote directory)
# A new directory is created every hour.
 
PICSDIR=/home/carol/pics
WEBDIR=/var/www/carol/webcam
 
while true; do 
        DATE=`date +%Y%m%d`
        HOUR=`date +%H`
        mkdir $WEBDIR/"$DATE"
        
        while [ $HOUR -ne "00" ]; do 
               DESTDIR=$WEBDIR/"$DATE"/"$HOUR"
               mkdir "$DESTDIR"
               mv $PICDIR/*.jpg "$DESTDIR"/
               sleep 3600
               HOUR=`date +%H`
        done
done

Σημειώστε τη χρήση της δήλωσης true. Αυτό σημαίνει: συνέχισε την εκτέλεση μέχρι να λάβεις σήμα τερματισμού (με kill ή Ctrl+C).

Αυτό το μικρό σενάριο μπορεί να χρησιμοποιηθεί για έλεγχο του προηγουμένου σεναρίου: δημιουργεί αρχεία:

 
#!/bin/bash
 
# This generates a file every 5 minutes
 
while true; do
touch pic-`date +%s`.jpg
sleep 300
done

Σημειώστε τη χρήση της εντολής date για τη δημιουργία ονομάτων αρχείων και καταλόγων. Δείτε τισ σελίδες τεκμηρίωσης για λεπτομέρειες.

Note

Πραγματική χρήση 

 

Το προηγούμενο παράδειγμα γράφτηκε έτσι για λόγους επίδειξης. Στη πραγματικότητα οι περιοδικές ενέργειες μπορούν να επιτευχθούν με την υπηρεσία cron του συστήματος. Μη ξεχνάτε να ανακατευθύνετε την έξοδο και τα σφάλματα των σεναρίων που εκτελούνται από το crontab!


9.2.2.3. Χρήση πληκτρολογίου για τον έλεγχο του βρόχου while

Αυτό το σενάριο μπορεί να διακοπεί από το χρήστη με την εισαγωγή Ctrl+C:

 
#!/bin/bash
 
# This script provides wisdom
 
FORTUNE=/usr/games/fortune
 
while true; do
echo "On which topic do you want advice?"
cat << topics
politics
startrek
kernelnewbies
sports
bofh-excuses
magic
love
literature
drugs
education
topics
 
echo
echo -n "Make your choice: "
read topic
echo
echo "Free advice on the topic of $topic: "
echo
$FORTUNE $topic
echo
 
done

Ένα here document παρουσιάζει στο χρήστη τις τρέχουσες επιλογές. Πάλι, η έλεγχος με true επαναλαμβάνει τις εντολές CONSEQUENT-COMMANDS συνεχώς.


9.2.2.4. Υπολογισμός μέσου όρου

Αυτό το σενάριο υπολογίζει το μέσο όρο από αριθμούς που εισάγει ο χρήστης. Η είσοδος ελέγχεται αν είναι στο σωστό εύρος τιμών και σε περίπτωση σφάλματος εμφανίζει μήνυμα. Αν πατηθεί το q ο βρόχος τερματίζεται (ο έλεγχος σφαλμάτων δεν είναι πλήρης).:

 
#!/bin/bash
 
# Calculate the average of a series of numbers.
 
SCORE="0"
AVERAGE="0"
SUM="0"
NUM="0"
 
while true; do
 
  echo -n "Enter your score [0-100%] ('q' for quit): "; read SCORE;
 
  if (("$SCORE" < "0"))  || (("$SCORE" > "100")); then
    echo "Be serious.  Common, try again: "
  elif [ "$SCORE" == "q" ]; then
    echo "Average rating: $AVERAGE%."
    break
  else
    SUM=$[$SUM + $SCORE]
    NUM=$[$NUM + 1]
    AVERAGE=$[$SUM / $NUM]
  fi
 
done
 
echo "Exiting."

Προσέξτε στις τελευταίες γραμμές οτι οι μεταβλητές μένουν χωρίς εισαγωγικά για να γίνουν αριθμητικές πράξεις.


9.3. Ο βρόχος until

9.3.1. Τι είναι;

Ο βρόχος until είναι πολύ όμοιος με το βρόχο while, εκτός από το γεγονός οτι ο βρόχος εκτελείται μέχρι ο έλεγχος TEST-COMMAND να είναι επιτυχής. Όσο ο έλεγχος αποτυγχάνει, ο βρόχος συνεχίζει. Η σύνταξη είναι όμοια με του βρόχου while:

until TEST-COMMAND; do CONSEQUENT-COMMANDS; done

Η κατάσταση εξόδου που επιστρέφεται είναι αυτή της τελευταίας εντολής από τη λίστα CONSEQUENT-COMMANDS, ή μηδέν, αν δεν εκτελεστεί καμμιά εντολή. Η TEST-COMMAND μπορεί πάλι νε είναι οποιαδήποτε εντολή επιστρέφει κατάσταση επιτυχίας ή αποτυχίας, και οι CONSEQUENT-COMMANDS μπορεί να είναι οποιεσδήποτε εντολές,σενάρια ή δομές φλοιού.

Όπως εξηγήθηκε προηγούμενα, το ";" μπορεί να αντικατασταθεί με μια ή περισσότερες αλλαγές γραμμής.


9.3.2. Παράδειγμα

Να ένα βελτιωμένο σενάριο picturesort.sh (δείτε Ενότητα 9.2.2.2), που ελέγχει για διαθέσιμο χώρο δίσκου. Αν δεν υπάρχει χώρος, διαγράφουμε εικόνες παλαιότερων μηνών:

 
#!/bin/bash
 
# This script copies files from my homedirectory into the webserver directory.
# A new directory is created every hour.
# If the pics are taking up too much space, the oldest are removed.
 
while true; do 
        DISKFUL=$(df -h $WEBDIR | grep -v File | awk '{print $5 }' | cut -d "%" -f1 -)
 
        until [ $DISKFUL -ge "90" ]; do 
 
               DATE=`date +%Y%m%d`
               HOUR=`date +%H`
               mkdir $WEBDIR/"$DATE"
                                                                                
               while [ $HOUR -ne "00" ]; do
                       DESTDIR=$WEBDIR/"$DATE"/"$HOUR"
                       mkdir "$DESTDIR"
                       mv $PICDIR/*.jpg "$DESTDIR"/
                       sleep 3600
                       HOUR=`date +%H`
               done
 
        DISKFULL=$(df -h $WEBDIR | grep -v File | awk '{ print $5 }' | cut -d "%" -f1 -)
        done
 
        TOREMOVE=$(find $WEBDIR -type d -a -mtime +30)
        for i in $TOREMOVE; do
               rm -rf "$i";
        done
 
done

Προσέξτε την αρχικοποίηση των μεταβλητών HOUR και DISKFULL και τη χρήση των επιλογών με τις εντολές ls και date ώστε να ληφθεί σωστά η λίστα TOREMOVE.


9.4. Ανακατεύθυνση Ε/Ε και βρόχοι

9.4.1. Ανακατεύθυνση εισόδου

Αντί για τον έλεγχο ενός βρόχου με βάση το αποτέλεσμα μιας εντολής ή την είσοδο του χρήστη, μπορούμε να ορίσουμε ως πηγή εισόδου ένα αρχείο. Σε τέτοιες περιπτώσεις, η εντολή ελέγχου είναι συχνά η  read. Όσο γραμμές εισόδου εισάγονται στο βρόχο, η εκτέλεση των εντολών συνεχίζεται. Όταν οι γραμμές εισόδου τελειώσουν, η εκτέλεση του βρόχου τερματίζεται.

Αφού η δομή βρόχου αντιμετωπίζεται ως μια εντολή (ας πούμε while TEST-COMMAND; do CONSEQUENT-COMMANDS; done), η ανακατεύθυνση εισάγεται μετά τη δήλωση done ώστε να διερμηνεύεται στη μορφή

command < file

Αυτός ο τύπος ανακατεύθυνσης δουλεύει και με τους υπόλοιπους βρόχους.


9.4.2. Ανακατεύθυνση εξόδου

Στο παρακάτω παράδειγμα, η έξοδος της εντολής find χρησιμοποιείται ως είσοδος της εντολής read που ελέγχει το βρόχο while:

 
[carol@octarine ~/testdir] cat archiveoldstuff.sh
#!/bin/bash
 
# This script creates a subdirectory in the current directory, to which old
# files are moved.
# Might be something for cron (if slightly adapted) to execute weekly or 
# monthly.
 
ARCHIVENR=`date +%Y%m%d`
DESTDIR="$PWD/archive-$ARCHIVENR"
 
mkdir $DESTDIR
 
find $PWD -type f -a -mtime +5 | while read file
do
gzip "$file"; mv "$file".gz "$DESTDIR"
echo "$file archived"
done

Τα αρχεία συμπιέζονται πριν μετακινηθούν στο κατάλογο αρχειοθέτησης.


9.5. Break και continue

9.5.1. Η break

Η break χρησιμοποιείται για την έξοδο από τον τρέχοντα βρόχο πριν την κανονική έξοδο. Χρησιμοποιείται όταν δεν γνωρίζουμε εκ των προτέρων πόσες φορές θα εκτελεστεί ο βρόχος, για παράδειγμα όταν η έξοδος από το βρόχο εξαρτάται από τα δεδομένα εισόδου. 

Το ακόλουθο παράδειγμα δείχνει πώς μπορεί να διακοπεί ένας βρόχος while. Πρόκειται για κάπως βελτιωμένη έκδοση του σεναρίου wisdom.sh από την Ενότητα 9.2.2.3.

 
#!/bin/bash
 
# This script provides wisdom
# You can now exit in a decent way.
 
FORTUNE=/usr/games/fortune
 
while true; do
echo "On which topic do you want advice?"
echo "1.  politics"
echo "2.  startrek"
echo "3.  kernelnewbies"
echo "4.  sports"
echo "5.  bofh-excuses"
echo "6.  magic"
echo "7.  love"
echo "8.  literature"
echo "9.  drugs"
echo "10. education"
echo
 
echo -n "Enter your choice, or 0 for exit: "
read choice
echo
 
case $choice in
     1)
     $FORTUNE politics
     ;;
     2)
     $FORTUNE startrek
     ;;
     3)
     $FORTUNE kernelnewbies
     ;;
     4)
     echo "Sports are a waste of time, energy and money."
     echo "Go back to your keyboard."
     echo -e "\t\t\t\t -- \"Unhealthy is my middle name\" Soggie."
     ;;
     5)
     $FORTUNE bofh-excuses
     ;;
     6)
     $FORTUNE magic
     ;;
     7)
     $FORTUNE love
     ;;
     8)
     $FORTUNE literature
     ;;
     9)
     $FORTUNE drugs
     ;;
     10)
     $FORTUNE education
     ;;
     0)
     echo "OK, see you!"
     break
     ;;
     *)
     echo "That is not a valid choice, try a number from 0 to 10."
     ;;
esac  
done

Προσέξτε οτι η break βγαίνει από το βρόχο, όχι από το σενάριο. Αυτό μπορεί να δειχτεί αν βάλουμε μια εντολή echo στο τέλος του σεναρίου. Αυτή η echo θα εκτελεστεί μετά τη break (όταν ο χρήστης εισέγει "0").

Σε ένθετους βρόχους, η break επιτρέπει το καθορισμό του βρόχου από τον οποίο βγαίνουμε, δείτε τις σελίδες info του Bash για περισσότερα.


9.5.2. Η continue

Η continue συνεχίζει την εκτέλεση ενός βρόχου for, while, until ή select από το επόμενο βήμα.

Όατν χρησιμοποιείται σε βρόχο for, η μεταβήτή ελέγχου λαμβάνεθ τη τιμή του επομένου στοιχείου της λίστας. Όταν όμως χρησιμοποιείται με δομή while ή until, η εκτέλεση συνεχίζεται με την TEST-COMMAND στην αρχή του βρόχου.


9.5.3. Παραδείγματα

Στο ακόλουθο παράδειγμα, τα ονόματα αρχείων μετατρέπονται όλα ώστε να περιέχουν μόνο πεζά γράμματα. Αν δεν απαιτείται μετατροπή, μια δήλωση continue συνεχίζει την εκτέλεση του βρόχου. Πιθανότατα το ίδιο πρόβλημα θα μπορούσε να λυθεί με τη χρήση sed και awk. ή θα μπορούσαμε να αφήσουμε το βρόχο να εκτελεστεί κανονικά, αφού η εργασία δεν είναι απαιτητική. Όμως η δομή continue είναι χρήσιμη αν οι εραγσίες είναι βαριές και η παράλειψή τους γλιτώνει πόρους του συστήματος.

 
[carol@octarine ~/test] cat tolower.sh
#!/bin/bash
 
# This script converts all file names containing upper case characters into file
# names containing only lower cases.
 
LIST="$(ls)"
 
for name in "$LIST"; do
 
if [[ "$name" != *[[:upper:]]* ]]; then
continue
fi
 
ORIG="$name"
NEW=`echo $name | tr 'A-Z' 'a-z'`
 
mv "$ORIG" "$NEW"
echo "new name for $ORIG is $NEW"
done

Το σενάριο αυτό έχει τουλάχιστο ένα μειονέκτημα: αντικαθιστά υπάρχοντα αρχεία. Η επιλογή  noclobber του Bash είναι χρήσιμη μόνο αν υπάρχει ανακατεύθυνση. Η επιλογή -b της εντολής mv παρέχει περισσότερη ασφάλεια, αλλά είναι χρήσιμο μόνο για μια συμπτωματική αντικατάσταση, όπως φαίνεται στον παρακάτω έλεγχο:

 
[carol@octarine ~/test] rm *
 
[carol@octarine ~/test] touch test Test TEST
 
[carol@octarine ~/test] bash -x tolower.sh
++ ls
+ LIST=test
Test
TEST
+ [[ test != *[[:upper:]]* ]]
+ continue
+ [[ Test != *[[:upper:]]* ]]
+ ORIG=Test
++ echo Test
++ tr A-Z a-z
+ NEW=test
+ mv -b Test test
+ echo 'new name for Test is test'
new name for Test is test
+ [[ TEST != *[[:upper:]]* ]]
+ ORIG=TEST
++ echo TEST
++ tr A-Z a-z
+ NEW=test
+ mv -b TEST test
+ echo 'new name for TEST is test'
new name for TEST is test
 
[carol@octarine ~/test] ls -a
./  ../  test  test~

Η εντολή tr είναι μέρος του πακέτου textutils και μπορεί να κάνει διαφόρων ειδών μετατροπές χαρακτήρων.


9.6. Δημιουργία menu με τη select

9.6.1. Γενικά

9.6.1.1. Χρήση της select

Η δομή select επιτρέπει την εύκολη παραγωγή menu. Η σύνταξη είναι παρόμοια με αυτή του βρόχου for:

select WORD [in LIST]; do RESPECTIVE-COMMANDS; done


Η LIST επεκτείνεται, παράγοντας μια λίστα στοιχείων. H επέκταση εμφανίζεται στο πρότυπο σφάλμα,  με ένα αριθμό πριν από κάθε στοιχείο.. Εάν το in LIST  δεν υπάρχει, εμφανίζονται οι παράμετροι θέσης, δηλαδή σαν να υπήρχε το in $@. Η LIST εμφανίζεται μόνο μια φορά.

Μετά την εμφάνιση όλων των στοιχείων, εμφανίζεται η προτροπή PS3 και διαβάζεται μια γραμμή από την πρότυπη είσοδο. Εάν αυτή η γραμμή αποτελείται από έναν αριθμό που αντιστοιχεί σε ένα από τα στοιχεία, η τιμή της μεταβλητής WORD τίθεται στο όνομα εκείνου του στοιχείου. Εάν η γραμμή είναι κενή, τα στοιχεία και η προτροπή PS3 εμφανίζονται πάλι. Εάν διαβαστεί ένας χαρακτήρας  EOF (τέλος αρχείου), ο βρόχος τερματίζεται. Δεδομένου ότι οι περισσότεροι χρήστες δεν γνωρίζουν ποιος είναι ο συνδυασμός πλήκτρων της ακολουθία EOF, είναι φιλικότερο προς το χρήστη να υπάρχει μεταξύ των στοιχείων και μια εντολή break. Οποιαδήποτε άλλη τιμή από τη γραμμή εισόδου θέτει στη WORD.μια άδεια συμβολοσειρά.

Η γραμμή εισόδου σώζεται στη μεταβλητή REPLY.

Οι RESPECTIVE-COMMANDS εκτελούνται μετά από κάθε επιλογή έως ότου διαβαστεί ο αριθμός που αντιπροσωπεύει την εντολή break . Αυτό τερματίζει το βρόχο.


9.6.1.2. Παραδείγματα

Αυτό είναι ένα πολύ απλό παράδειγμα, αλλά όπως μπορείτε να δείτε, δεν είναι ιδιαίτερα φιλικό στο χρήστη:

 
[carol@octarine testdir] cat private.sh
#!/bin/bash
 
echo "This script can make any of the files in this directory private."
echo "Enter the number of the file you want to protect:"
 
select FILENAME in *;
do
     echo "You picked $FILENAME ($REPLY), it is now only accessible to you."
     chmod go-rwx "$FILENAME"
done
 
[carol@octarine testdir] ./private.sh
This script can make any of the files in this directory private.
Enter the number of the file you want to protect:
1) archive-20030129
2) bash
3) private.sh
#? 1
You picked archive-20030129 (1)
#?

Η ρύθμιση της προτροπής PS3 και η πρόσθεση μιας επιλογής quit βελτιώνει τη κατάσταση:

 
#!/bin/bash
 
echo "This script can make any of the files in this directory private."
echo "Enter the number of the file you want to protect:"
 
PS3="Your choice: "
QUIT="QUIT THIS PROGRAM - I feel safe now."
touch "$QUIT"
 
select FILENAME in *;
do
  case $FILENAME in
        "$QUIT")
          echo "Exiting."
          break
          ;;
        *)
          echo "You picked $FILENAME ($REPLY)"
          chmod go-rwx "$FILENAME"
          ;;
  esac
done
rm "$QUIT"

9.6.2. Υπο-menu

Μια δήλωση μέσα στη δομή select μπορεί να είναι μια νέα δήλωση select, επιτρέποντας έτσι την δημιουργία υπο-menu σε ένα menu.

Ως προεπιλογή, η προτροπή PS3 δεν μεταβάλλεται όταν μπαίνουμε σε ένθετη select. Αν θέλετε κάτι τέτοιο, πρέπει να μεταβάλλετε τη προτροπή τη κατάλληλη στιγμή.


9.7. Η shift

9.7.1. Τι κάνει;

Η εντολή shift είναι μια εσωτερική εντολή του φλοιού Bourne που υπάρχει και στο BashΑυτή η εντολή παίρνει ένα όρισμα, έναν αριθμό. Οι παράμετροι θέσης μετατοπίζονται προς τα αριστερά με βάση αυτόν τον αριθμό, N. Οι παράμετροι θέσης από N+1 εως $# μετονομάζονται σε $1 εως $# - N+1

Έστω ότι έχετε μια εντολή που δέχευται 10 ορίσματα, και το N είναι 4. Τότε το $4 γίνεται $1,  το $5 γίνεται $2 κλπ. Το $10 γίνεται $7 και τα αρχικά $1$2 και $3 χάνονται.

Εάν το N είναι μηδέν ή μεγαλύτερο από $# (ο συνολικός αριθμός ορισμάτων, δείτε Ενότητα 7.2.1.2), ή εάν το  N δεν υπάρχει, τότε λαμβάνει τη τιμή 1. Η κατάσταση εξόδου είναι μηδέν εκτός αν το N είναι μεγαλύτερο από $# ή μικρότερο από μηδέν.


9.7.2. Παραδείγματα

Μια δήλωση shift τυπικά χρησιμοποιείται όταν ο αριθμός των ορισμάτων σε μια εντολή δεν είναι γνωστός εκ των προτέρων, για παράδειγμα όταν οι χρήστες μπορούν να δώσουν όσα ορίσματα θέλουν. Σε τέτοιες περιπτώσεις, η επεξεργασία των ορισμάτων γίνεται μέσω ενός βρόχου while με συνθήκη ελέγχου της μορφής  (( $# )). Αυτή η συνθήκη είναι αληθής όσο ο αριθμός των ορισμάτων είναι μεγαλύτερος του μηδενός. Η επεξεργασία των ορισμάτων γίνεται με τη μεταβλητή $1 και τη δήλωση shift. Ο αριθμός των ορισμάτων μειώνεται κάθε φορά που εκτελείται η shift και στο τέλος γίνεται μηδέν, και ο βρόχος while τερματίζεται.

Το παρακάτω παράδειγμα, cleanup.sh, χρησιμοποιεί δηλώσεις shift για την επεξεργασία κάθε αρχείου στη λίστα που δημιουργείται με τη find:

 
#!/bin/bash
 
# This script can clean up files that were last accessed over 365 days ago.
 
USAGE="Usage: $0 dir1 dir2 dir3 ... dirN"
 
if [ "$#" == "0" ]; then
        echo "$USAGE"
        exit 1
fi
 
while (( "$#" )); do
 
if [[ "$(ls $1)" == "" ]]; then 
        echo "Empty directory, nothing to be done."
  else 
        find $1 -type f -a -atime +365 -exec rm -i {} \;
fi
 
shift
 
done

 

Note

-exec έναντι xargs

 

Η παραπάνω εντολή find μπορεί να αντικατασταθεί με την ακόλουθη:

find options | xargs [commands_to_execute_on_found_files]

Η εντολή xargs κτίζει και εκτελεί γραμμές εντολών από τη πρότυπη είσοδο. Αυτό έχει το πλεονέκτημα οτι η γραμμή εντολών συμπληρώνεται μέχρι το όριο του συστήματος. Μόνο τότε η εντολή θα κληθεί να εκτελεστεί, στο παραπάνω παράδειγμα είναι η εντολή rm. Αν υπάρχουν περισσότερα ορίσματα, θα χρησιμοποιηθέι μια νέα γραμμή εντολών, μέχρι και αυτή να γεμίσει ή να τελειώσουν τα ορίσματα. Η δομή find -exec καλεί την εντολή προς εκτέλεση καε φορά που βρίσκεται ένα αρχείο. Έτσι η χρήση της xargs επιταχύνει πολύ τα σενάρια και βελτιώνει την απόδοση του συστήματός σας.

Στο επόμενο παράδειγμα, τροποποιήσαμε το σενάριο της Ενότητας 8.2.4.4 ώστε να δέχεται πολλπλά πακέτα προς εγκατάσταση.

 
#!/bin/bash
if [ $# -lt 1 ]; then
        echo "Usage: $0 package(s)"
        exit 1
fi
while (($#)); do
        yum install $1 << CONFIRM
y
CONFIRM
shift
done

9.8. Περίληψη

Σε αυτό το κεφάλαιο, συζητήσαμε πώς επαναλαμβανόμενες εργασίες μπορούν να ενσωματωθούν σε βρόχους. Οι περισσότεροι κοινοί βρόχοι δημιουργούνται με την χρήση των δηλώσεων for, while ή until ή έναν συνδυασμό αυτών των εντολών. Ο βρόχος for εκτελεί μια εργασία για καθορισμένο αριθμό επαναλήψεων. Εάν δεν ξέρετε πόσες φορές μια εντολή πρέπει να εκτελεστεί, τότε χρησιμοποιήστε είτε until είτε while για να ορίσετε πότε ο βρόχος πρέπει να τερματιστεί. 

Οι βρόχοι μπορούν να διακοπούν ή να συνεχιστούν χρησιμοποιώντας τις δηλώσεις break και continue

Ένα αρχείο μπορεί να χρησιμοποιηθεί ως είσοδος σε έναν βρόχο με τη βοήθεια ανακατεύθυνσης, οι βρόχοι μπορούν επίσης να διαβάσουν την έξοδο από εντολές μέσω σωλήνωσης. 

Η δομή select χρησιμοποιείται για δημιουργία menu στα διαλογικά σενάρια. Η βηματική επεξεργασία των ορσιμάτων γραμμών εντολής σε ένα σενάριο μπορεί να επιτευχθεί με τη shift.


9.9. Ασκήσεις

(Θυμηθείτε: ότι κατά την κατασκευή των σεναρίων, εργαστείτε με βήματα και εξετάστε κάθε βήμα πριν το ενσωματώσετε στο σενάριό σας. 

1.      Δημιουργήστε ένα σενάριο που θα αντιγράφει αναδρομικά τα αρχεία του /etc ώστε ένας αρχάριος διαχειριστής συστημάτων να τροποποιήσει τα αρχεία χωρίς φόβο.

2.      Γράψτε ένα σενάριο που δέχεται ακριβώς ένα όρισμα, ένα όνομα καταλόγου. Εάν ο αριθμός ορισμάτων είναι μεγαλύτερος ή μικρότερος από ένα, εμφανίστε ένα μήνυμα χρήσης. Εάν το όρισμμα δεν είναι κατάλογος, εμφανίστε ένα άλλο μήνυμα. Για το δεδομένο κατάλογο, εμφανίτε τα πέντε μεγαλύτερα αρχεία και τα πέντε αρχεία που τροποποιήθηκαν πιο πρόσφατα.

3.      Μπορείτε να εξηγήσετε γιατί είναι τόσο σημαντικό να τεθούν οι μεταβλητές μεταξύ των διπλών εισαγωγικών στο παράδειγμα της Ενότητας 9.4.2;

4.      Γράψτε ένα σενάριο παρόμοιο με αυτό της Ενότητας 9.5.1, αλλά σκεφτείτε έναν τρόπο τερματισμού αφού ο χρήστης έχει εκτελέσει 3 επαναλήψεις.

5.      Σκεφτείτε μια καλύτερη λύση από την mv -b για το σενάριο της Ενότητας 9.5.3 για να αποτρέψει την αντικατάσταση των υπαρχόντων αρχείων. Παραδείγματος χάριν, έλεγχος ύπαρξης ενός αρχείου. Μην κάνετε περιττή εργασία!

6.      Ξαναγράψτε το σενάριο whichdaemon.sh από την Ενότητα 7.2.4, έτσι ώστε

o        Να τυπώνει μια λίστα διακομιστών προς έλεγχο, όπως Apache, SSH, NTP, DNS, διαχειριστή ισχύος, κλπ.

o        Για κάθε επιλογή ο χρήστης μπορεί , να εμφανίσει κάποιες εύλογες πληροφορίες, όπως το όνομα του διακομιστή ιστού, πληροφορίες ιχνών NTP, κλπ.

o        Προαιρετικά, ενσωματώστε μια δυνατότητα για τους χρήστες να ελέγξουν άλλους διακομιστές από αυτούς που απαριθμούνται. Για τέτοιες περιπτώσεις, ελέγξτε ότι τουλάχιστον η δεδομένη διεργασία εκτελείται. 

o        Αναθεωρείστε το σενάριο στην Ενότητα 9.2.2.4. Σημειώστε πώς η εισαγωγή χαρακτήρα εκτός από το q γίνεται δεκτή χωρίς σφάλμα.. Ξαναγράψτε το σενάριο έτσι ώστε να τυπώνει ένα μήνυμα εάν εισάγονται χαρακτήρες.


Κεφάλαιο 10. Περισσότερα για μεταβλητές

Σε αυτό το κεφάλαιο, θα συζητήσουμε τη προχωρημένη χρήση μεταβλητών και ορισμάτων. Με τη συμπλήρωση του κεφαλαίου θα μπορείτε να:

·         Δηλώνετε και χρησιμοποιείτε πίνακες μεταβλητών

·         Καθορίζετε το είδος της μεταβλητής που θέλετε να χρησιμοποιήσετε

·         Ορίσετε μεταβλητές μόνο για ανάγνωση

·         Χρησιμοποιήσετε τη set για εκχώρηση τιμής σε μια μεταβλητή


10.1. Τύποι μεταβλητών

10.1.1. Γενική εκχώρηση τιμών

Όπως έχουμε ήδη δεί, το Bash αναγνωρίζει διαφορετικά είδη μεταβλητών και παραμέτρων. Μέχρι τώρα δεν ασχοληθήκαμε με το είδος των μεταβλητών, έτσι ώστε κάθε μεταβλητή μπορεί να αποθήκευε οποιαδήποτε τιμή. Ένα απλό παράδειγμα από τη γραμμή εντολών::

 
[bob in ~] VARIABLE=12
 
[bob in ~] echo $VARIABLE
12
 
[bob in ~] VARIABLE=string
 
[bob in ~] echo $VARIABLE
string

Υπάρχουν περιπτώσεις που θέλετε να αποφύγετε αυτού του τύπου τη συμπεριφορά, για παράδειγμα ότνα διαχειρίζεστε αριθμούς τηλεφώνου ή άλλους αριθμούς. Εκτός από ακεραίους και συμβολοσειρές, μπορεί να θέλετε να ορίσετε μια σταθερά. Αυτί συχνά γίνεται στην αρχή του σεναρίου, όπου δίνεται και η τιμή της σταθεράς. Μετά από αυτό, υπάχουν μόνο αναφορές στο όνομα της σταθεράς, έτσι ώστε οι όποιες αλλαγές να συμβαίνουνι σε ένα μόνο σημείο του σεναρίου. Μια μεταβλητή επίσης μπορεί να αποτελεί πίνακα μεταβλητών (VAR0, VAR1, VAR2, ... VARN).


10.1.2. Χρήση της declare 

Με τη δήλωση declare, μπορούμε να περιορίσουμε την εκχώρηση τιμών σε μεταβλητές.

Η σύνταξη της declare είναι η ακόλουθη:

declare OPTION(s) VARIABLE=value

Οι παρακάτω επιλογές χρησιμοποιούνται για τον ορισμό του τύπου  και άλλων χαρακτηριστικών της μεταβλητής.

Πίνακας 10-1. Επιλογής της declare

Επιλογή

Σημασία

-a

Η μεταβλητή είναι πίνακας.

-f

Χρήση μόνο ονομάτων συναρτήσεων

-i

Η μεταβλητή είναι ακέραια, γίνονται αριθμητικές πράξεις (δείτε Ενότητα 3.4.6).

-p

Εμφάνιση χαρακτηριστικών και τιμών μεταβλητών. Με την επιλογή -p οι άλλες επιλογές αγνοούνται.

-r

Η μεταβλητή είναι μόνο για ανάγνωση. Δεν μπορεί να πάρει άλλη τιμή ή να επανακαθοριστεί.

-t

Χαρακτηριστικό trace (ιχνηλάτηση).

-x

Εξαγωγή σε εντολές μέσω περιβάλλοντος.

Η χρήση + αντί για - ακυρώνει το χαρακτηριστικό. Σε μια συνάρτηση η declare δημιουργεί τοπικές μεταβλητές.

Τα παραδείγματα δείχνουν πως μια μεταβλητή επηρεάζεται από τα χαρακτηριστικά της.

 
[bob in ~] declare -i VARIABLE=12
 
[bob in ~] VARIABLE=string
 
[bob in ~] echo $VARIABLE
0
 
[bob in ~] declare -p VARIABLE
declare -i VARIABLE="0"

Σημειώστε οτι το Bash έχει επιλογή δήλωσης αριθμητικής μεταβλητής αλλά όχι συμβολοσειράς. Αυτό γιατί η συμβολοειρά είναι ο προεπιλεγμένος τύπος των ματαβλητών.

 
[bob in ~] OTHERVAR=blah
 
[bob in ~] declare -p OTHERVAR
declare -- OTHERVAR="blah"

Εφ' όσον δηλωθεί κάποιος τύπος, τότε η μεταβλητή μπορεί να λάβει τιμές αυτού του τύπου. Πιθανοί περιορισμοί: ακέραιος, σταθερά, πίανκας.

Δείτε τις σελίδες εγχειριδίου του Bash για πληροφορίες της κατάστασης εξόδου.


10.1.3. Σταθερές

Στο Bash, οι σταθερές δημιουργούνται καθιστώντας μια μεταβλητή 'μονο ανάγνωσης'.  Η εσωτερική εντολή readonly ορίζει μια μεταβλητή ως μονο ανάγνωσης. Η σύνταξη είναι:

readonly OPTION VARIABLE(s)

Οι τιμές αυτών των μεταβλητών δεν μπορούν να αλλάξουν με μετέπειτα εκχώρηση. Αν δοθεί η επιλογή -f, κάθε μεταβλητήα αναφέρεται σε μια συνάρτηση φλοιού, δείτε Κεφάλαιο 11. Αν οριστεί η επιλογή -a, κάθε μεταβλητή αναφέρεται σε ένα πίνακα μεταβλητών. Αν δεν δοθούν ορίσματα, ή αν δοθεί η επιλογή -p, εμφανίζεται μια λίστα με μεταβλητές μόνο-ανάγνωσης. Με την επιλογή  -p, η έξοδος μπορεί να επαναχρησιμοποιηθεί ως είσοδος.

Η κατασταση εξόδου είναι μηδέν, εκτός αν οριστεί μια άκυρη επιλογή ή καποια μεταβλητή ή συνάρτηση δεν υπάρχει, στη επιλογή -f δοθεί όνομα μεταβλητής αντί συνάρτησης.

 
[bob in ~] readonly TUX=penguinpower
 
[bob in ~] TUX=Mickeysoft
bash: TUX: readonly variable

10.2. Πίνακες μεταβλητών

10.2.1. Δημιουργία πινάκων

Ένας πίνακας είναι μια μεταβλητή που περιέχει πολλαπλές τιμές. Κάθε μεταβλητή μπορεί να χρησιμοποιηθεί ως πίνακας. Δεν υπάρχει ανώτατο όριο στο μέγεθος ενός πίνακα, ούτε κάποια απαίτηση οτι οι τιμές πρέπει να δεικτοδοτούνται ή να εκχωρούνται συνεχόμενα. Οι πίνακες ξεκινούν από το μηδενικό στοιχείο.

Η έμμεση δήλωση γίνεται με τη παρακάτω σύνταξη:

ARRAY[INDEXNR]=value

Το INDEXNR είναι μια αριθμητική έκφραση που πρέπει να παράγει ένα μη-αρνητικό αριθμό.

Η άμεση δήλωση πίνακα γίνεται με την declare:

declare -a ARRAYNAME

Η δήλωση μπορεί να συνοδεύεται από δείκτη, αλλά αυτός αγνοείται. Χαρακτηριστικά μπορούν να αποδοθούν με τις εντολές declare και readonly. Τα χαρακτηριστικά ισχύουν για όλα τα στοιχεία του πίνακα.

Οι μεταβλητές πίνακα μπορούν επίσης να δημιουργηθούν με σύνθετες εκχωρήσεις στη μορφή:

ARRAY=(value1 value2 ... valueN)

Κάθε τιμή έχει τη μορφή [indexnumber=]string. Ο δείκτης είναι προαιρετικός. Αν δεν δοθεί, τότε χρησιμοποιείται ο αμέσως επόμενος από τον τελευταίο που χρησιμοποιήθηκε. Η ίδια μορφή γίνεται δεκτή και στην declare. Αν δεν δοθεί δείκτης η αρίθμηση ξεκινά από το μηδέν.

Η πρόσθεση νέων ή επιπλέον στοιχέιων γίνεται με τη σύνταξη:

ARRAYNAME[indexnumber]=value

Θυμηθείτε οτι η εντολή read παρέχει την επιλογή -a, που επιτρέπει την ανάγνωση και εκχώρηση τιμών σε στοιχεία πίνακα.


10.2.2. Αναφορά στα στοιχεία ενός πίνακα

Για να αναφερθούμε στη τιμή ενός στοιχειου πίνακα, χρησιμοποιούμε αγκύλες. Αυτό είναι απαραίτητο, όπως φαίνεται στο παρακάτω παράδειγμα, για να παρακάμψουμε την διερμηνεία των τελεστών επέκτασης από το φλοιό. Αν ο δείκτης είναι @ ή *, τότε αναφέρονται όλα τα στοχιεία του πίανακα.

 
[bob in ~] ARRAY=(one two three)
 
[bob in ~] echo ${ARRAY[*]}
one two three
 
[bob in ~] echo $ARRAY[*]
one[*]
 
[bob in ~] echo ${ARRAY[2]}
three
 
[bob in ~] ARRAY[3]=four
 
[bob in ~] echo ${ARRAY[*]}
one two three four

Η αναφορά σε τιμή πίνακα χωρίς δείκτη, ταυτίζεται με την αναφορά στο μηδενικό στοιχείο του πίνακα.


10.2.3. Διαγραφή πινάκων μεταβλητών

Η εσωτερική εντολή unset καταστρέφει πόνακες μεταβλητών ή στοιχέια πινάκων μεταβλητών:

 
[bob in ~] unset ARRAY[1]
 
[bob in ~] echo ${ARRAY[*]}
one three four
 
[bob in ~] unset ARRAY
 
[bob in ~] echo ${ARRAY[*]}
<--no output-->

10.2.4. Παραδείγματα με πίνακες

Τα πρακτικά παραδείγματα με πίνακες είναι δυσεύρετα. Θα βρείτε πολλά παραδείγματα που δεν κάνουν στην ουσία τίποτε παραπάνω από αριθμητικούς υπολογισμούς σε πίνακες αριθμών, για παράδειγμα. Και αυτά είναι τα πιο ενδιαφέροντα, ίσως... τα περισσότερα παραδείγματα είναι υπεραπλουστευμένα και πολύ θεωρητικά.

Ο λόγος είναι οτι οι πίνακες είναι αρκετά σύνθετες δομές. Θα διαπιστώσετε οτι οι περισσότερες πρακτικές εφαρμογές πινάκων είναι γραμμένες στη γλώσσα C όπως και το μεγαλύτερο μέρος των εντολών του UNIX. Ένα καλό παρ'αδειγμα είναι η εσωτερική εντολή του Bash, history. Όσοι ενδιαφέρονται μπορούν να ελέγξουν το κατάλογο built-ins στον κώδικα του Bash και να δούν το fc.def, που υφίσταται επεξεργασία κατά τη μεταγλώττιση των εσωτερικών εντολών.

Ένας άλλος λόγος είναι οτι μερικοί φλοιοί δεν υποστηρπιζουν πίνακες, και έτσι σενάρια με πίνακες δεν είναι εύκολα μεταφερτά.

Μετά από μακρά αναζήτηση, τελικά βρήκα αυτό το παράδειγμα σε ένα πάροχο Internet. Διανέμει αρχεία διαμόρφωσης του διακομιστή ιστού Apache σε μια φάρμα διακομιστών ιστού :

 
#!/bin/bash
 
# $Id: chap10.xml,v 1.8 2005/09/05 12:39:22 tille Exp $
# $Log: chap10.xml,v $
# Revision 1.8  2005/09/05 12:39:22  tille
# sorry made a mistake
#
# Revision 1.6  2005/03/01 19:39:20  tille
# removed blank tracer images, added info on future debugging features, more keywords, minor corrections.
#
# Revision 1.5  2004/12/06 12:27:09  tille
# changes for new domainname, minor corrections
#
# Revision 1.6  2004/10/18 18:58:06  tille
# debugging, typos removed, replaced screenshots in chap9 with screen sections.
#
# Revision 1.5  2004/06/24 14:02:48  tille
# dded tracer image
#
# Revision 1.4  2004/06/15 08:47:12  tille
# more markup, index
#
# Revision 1.3  2004/05/22 13:34:18  tille
# review for fultus
#
# Revision 1.2  2004/04/26 13:24:41  tille
# updates by tabatha
#
# Revision 1.1.1.1  2004/02/11 16:59:50  tille
# initiele bash import
#
# Revision 1.3  2003/02/05 09:52:53  mbounine
# httpd restarting added.
#
# Revision 1.2  2003/02/05 08:11:32  mbounine
# Bug fixes.
#
# Revision 1.1  2003/02/04 15:41:35  mbounine
# Script for syncing httpd config between web farm hosts.
# Initial release.
#
if [ $(whoami) != 'root' ]; then
        echo "Must be root to run $0"
        exit 1;
fi
if [ -z $1 ]; then
        echo "Usage: $0 </path/to/httpd.conf>"
        exit 1
fi
 
httpd_conf_new=$1
httpd_conf_path="/usr/local/apache/conf"
login=htuser
 
farm_hosts=(web03 web04 web05 web06 web07)
 
for i in ${farm_hosts[@]}; do
        su $login -c "scp $httpd_conf_new ${i}:${httpd_conf_path}"
        su $login -c "ssh $i sudo /usr/local/apache/bin/apachectl graceful"
 
done
exit 0

Οι πρώτοι δύο έλεγχοι διαπιστώνουν αν πρόκειται για τον σωστό χρήστη και αν έχουν εισαχθεί τα σωστά ορίσματα. Τα ονόματα των διακομιστών που θα διαμορφωθούν βρίσκονται στον πίνακα farm_hosts. Μετά όλοι αυτοί οι διακομιστές λαμβάνουν το αρχείο διαμόρφωσης Apache, και στη συνέχεια ο δαίμονας επανεκκινείται. Σημειώστε τη χρήση των εντολών του πακέτου Secure Shell, για τη κρυπτογράφηση της επικοινωνίας μεταξύ των διακομιστών.

Ευχαριστώ τον Eugene και τους συνεργάτες γι´ αυτή τη συνεισφορά.

Ο Dan Richter συνεισέφερε το παρακάτω παράδειγμα. Το πρόβλημα που αντιμετώπισε είναι το εξής:

"...Στην εταιρία μου, στον ιστοχώρο μας έχουμε προγράμματα επίδειξης, και κάθε εβδομάδα κάποιος πρέπει να τα ελέγχει όλα. Γι'αυτό έχω μια εργασία cron που γεμίζει ένα πίνακα με τους πιθανούς υποψηφίους, χρησιμοποιεί το date +%W για να βρεί την εβδομάδα του έτους, και εκτελεί μια λειτουργία modulo για να βρεί το σωστό δείκτη. Ο τυχερός ειδοποιείται με by e-mail."

Να και μια λύση:

 
#!/bin/bash
# This is get-tester-address.sh 
#
# First, we test whether bash supports arrays.
# (Support for arrays was only added recently.)
#
whotest[0]='test' || (echo 'Failure: arrays not supported in this version of
bash.' && exit 2)
                                                                                
#
# Our list of candidates. (Feel free to add or
# remove candidates.)
#
wholist=(
     'Bob Smith <bob@example.com>'
     'Jane L. Williams <jane@example.com>'
     'Eric S. Raymond <esr@example.com>'
     'Larry Wall <wall@example.com>'
     'Linus Torvalds <linus@example.com>'
   )
#
# Count the number of possible testers.
# (Loop until we find an empty string.)
#
count=0
while [ "x${wholist[count]}" != "x" ]
do
   count=$(( $count + 1 ))
done
                                                                                
#
# Now we calculate whose turn it is.
#
week=`date '+%W'`      # The week of the year (0..53).
week=${week#0}         # Remove possible leading zero.
                                                                                
let "index = $week % $count"   # week modulo count = the lucky person
 
email=${wholist[index]}     # Get the lucky person's e-mail address.
                                                                                
echo $email            # Output the person's e-mail address.

Αυτό το σενάριο χρησιμοποιείται, όπως το ακόλουθο, που χρησιμοποιεί ένα here document:

 
email=`get-tester-address.sh`   # Find who to e-mail.
hostname=`hostname`             # This machine's name.
                                                                                
#
# Send e-mail to the right person.
#
mail $email -s '[Demo Testing]' <<EOF
The lucky tester this week is: $email
                                                                                
Reminder: the list of demos is here:
    http://web.example.com:8080/DemoSites
                                                                                
(This e-mail was generated by $0 on ${hostname}.)
EOF

10.3. Λειτουργίες σε μεταβλητές

10.3.1. Αριθμητική μεταβλητών

Το συζητήσαμε ήδη στην Ενότητα 3.4.6.


10.3.2. Μήκος μεταβλητής

Με τη σύνταξη ${#VAR} υπολογίζουμε τον αριθμό των χαρακτήρων μιας μεταβλητής. Αν η VAR είναι "*" ή "@", αυτή η τιμή αντικαθίσταται με τον αριθμό των παραμέτρων θέσης ή τον αριθμό των στοιχείων σε ένα πίνακα. Αυτό φαίνεται στο παρακάτω παράδειγμα:

 
[bob in ~] echo $SHELL
/bin/bash
 
[bob in ~] echo ${#SHELL}
9
 
[bob in ~] ARRAY=(one two three)
 
[bob in ~] echo ${#ARRAY}
3

10.3.3. Μετατροπές μεταβλητών

10.3.3.1. Αντικατάσταση

${VAR:-WORD}

Αν η VAR δεν ορίζεται ή είναι κενή (null), αντικαθίσταται η επέκταση του WORD, αλλιώς αντικαθίσταται η τιμή της VAR:

 
[bob in ~] echo ${TEST:-test}
test
 
[bob in ~] echo $TEST
 
 
[bob in ~] export TEST=a_string
 
[bob in ~] echo ${TEST:-test}
a_string
 
[bob in ~] echo ${TEST2:-$TEST}
a_string

Αυτή η μορφή χρησιμοποιείται σε ελέγχους συνθηκών, λόγου χάρη αυτός:

 
[ -z "${COLUMNS:-}" ] && COLUMNS=80

Είναι μια συντομότερη σύνταξη του

 
if [ -z "${COLUMNS:-}" ]; then
        COLUMNS=80
fi

Δείτε την Ενότητα 7.1.2.3 για περισσότερες πληροφορίες γι' αυτό το τύπο ελέγχου συνθηκών.

Αν η παύλα (-) αντικατασταθεί με το ίσον (=), η τιμή εκχωρείται στη παράμετρο:

 
[bob in ~] echo $TEST2
 
 
[bob in ~] echo ${TEST2:=$TEST}
a_string
 
[bob in ~] echo $TEST2
a_string

Η ακόλουθη σύνταξη ελέγχει την ύπαρξη μεταβλητής. Αν δεν υπάρχει εμφανίζεται η επέκταση του WORD στη πρότυπη έξοδο και ο μη-διαλογικός φλοιός τερματίζεται. Ένα παράδειγμα:

 
[bob in ~] cat vartest.sh
#!/bin/bash
 
# This script tests whether a variable is set.  If not,
# it exits printing a message.
 
echo ${TESTVAR:?"There's so much I still wanted to do..."}
echo "TESTVAR is set, we can proceed."
 
[bob in testdir] ./vartest.sh
./vartest.sh: line 6: TESTVAR: There's so much I still wanted to do...
 
[bob in testdir] export TESTVAR=present
 
[bob in testdir] ./vartest.sh
present
TESTVAR is set, we can proceed.

Η χρήση του "+" αντί για το θαυμαστικό δίνει στη μεταβλητή ως τιμή την επέκταση του WORD. Αν δεν υπάρχει δεν συμβαίνει τίποτε.


10.3.3.2. Διαγραφή τμημάτων συμβολοσειρών

Η ακόλουθη σύνταξη αφαιρεί ένα αριθμό χαρακτήρων, ίσο με OFFSET, από μια μεταβλητή:

${VAR:OFFSET:LENGTH}

Η παράμετρος LENGTH ορίζει πόσοι χαρακτήρες θα διατηρηθούν, ξεκινώντας από τον πρώτο χαρακτήρα μετά το OFFSET. Αν το LENGTH παραληφθεί, τότε λαμβάνεται όλο η υπόλοιπη συμβολοσειρά:

 
[bob in ~] export STRING="thisisaverylongname"
 
[bob in ~] echo ${STRING:4}
isaverylongname
 
[bob in ~] echo ${STRING:6:5}
avery

${VAR#WORD}

και

${VAR##WORD}

Αυτές οι δομές χρησιμοποιούνται για τη διαγραφή του προτύπου που ταυτίζεται με την επέκαταση του WORD στη μεταβλητή VAR. Το WORD επεκτείνεται για να παράγει ένα πρότυπο όπως και στη περίπτωση των ονομάτων αρχείων. Το απλό hash ("#") ταυτίζει το μικρότερο δυνατό πρότυπο ενώ το διπλό ("##") το μεγαλύτερο δυνατό (μέχρι να βρεθεί χαρακτήρας οριοθέτησης) από την αρχή της συμβολοσειράς μεταβλητής.

Αν η VAR είναι * ή @, η λειτουργία αφαίρεσης πτοτύπου εφαρμόζεται σε κάθε παράμετρο θέσης με τη σειρά.

Αν η VAR είναι πίνακας και συνοδεύεται από "*" ή "@", η διαγραφή αφαρμόζεται σε κάθε στοιχείο, όπως φαίνεται στο παράδειγμα:

 
[bob in ~] echo ${ARRAY[*]}
one two one three one four
 
[bob in ~] echo ${ARRAY[*]#one}
two three four
 
[bob in ~] echo ${ARRAY[*]#t}
one wo one hree one four
 
[bob in ~] echo ${ARRAY[*]#t*}
one wo one hree one four
 
[bob in ~] echo ${ARRAY[*]##t*}
one one one four

Η χρήση "%" and "%%", έχει παρόμοια αποτελέσματα αλλά εφαρμόζεται από το τέλος της συμβολοσειράς της μεταβλητής:

 
[bob in ~] echo $STRING
thisisaverylongname
 
[bob in ~] echo ${STRING%name}
thisisaverylong

10.3.3.3. Αντικατάσταση τμημάτων συμβολοσειρών

Αυτό γίνεται με τη δομή

${VAR/PATTERN/STRING}

ή

${VAR//PATTERN/STRING}

Η πρώτη αντικαθιστά μόνο τη πρώτη ταύτιση ενώ η δεύτερη κάθε ταύτιση του PATTERN με το STRING:

 
[bob in ~] echo ${STRING/name/string}
thisisaverylongstring

Περισσότερες πληροφορίες στις σελίδες εγχειριδίου του Bash.


10.4.  Περίληψη

Κανονικά, μια μεταβλητή μπορεί να αποθηκεύσει οποιοδήποτε τύπο δεδομένω, εκτός και αν υπάρχει ρητή δήλωση τύπου μεταβλητής. Οι σταθερές δηλώνονται με την εσωτερική εντολή readonly.

Ένας πίνακας αποθεκεύει μια σειρά όμοιων μεταβλητών. Αν έχει δηλωθεί τύπος δεδομένων, τότε όλα τα στοιχεία του πίνακα πρέπει να ανήκουν σε αυτό το τύπο.

Χαρακτηριστικά του Bash επιτρέπουν αντικατάσταση και μετασχηματισμό των μεταβλητών. Τυπικές λειτουργίες περιλαμβάνουν τον υπολογισμό του μήκους μεταβλητών, αριθμητική μεταβλητών, αντικατάσταση περιεχομένου (ή τμήματος του περιεχομένου) μεταβλητών.


10.5. Ασκήσεις

Μερικές σπαζικεφαλιές:

1.      Γράψτε ένα σενάριο που εκτελεί τα παρακάτω:

o        Εμφανίζει το όνομα του σεναρίου που εκτελείται.

o        Εμφανίζει το πρώτο, τρίτο και δέκατο όρισμα του σεναρίου.

o        Εμφανίζει τον συνολικό αριθμό ορισμάτων που περάσαν στο σενάριο.

o        Αν υπάρχουν περισσότερες απο τρείς παράμετροι θέσης, μετακινείστε τις 3 θέσεις αριστρέα με τη shift.

o        Εμφανίστε τις τιμές των ορισμάτων που απομένουν.

o        Εμφανίστε τον αριθμό των ορισμάτων.

Ελέγξτε το σενάριο με μηδέν, ένα, δύο, τρία και πάνω από δέκα ορίσματα.

2.      Γράψτε ένα σενάριο που υλοποιεί ένα απλό περιηγητή ιστού (μόνο για κείμενο), με τη βοήθεια του μεταφορτωτή wget και του περιηγητή links -dump για την εμφάνιση σελίδων HTML στον χρήστη. Ο χρήστης έχει 3 επιλογές: εισγωγή ενός URL, εισαγωγή b για 'πίσω' και q για τερματισμό. Τα τελευταία 10 URL's που εσιήγαγε ο χρήστης αποθηκέυονυται σε ένα πίνακα, από όπου ο χρήστης μπορεί να ανακαλέσει ένα URL με τη βοήθεια του b.


Κεφάλαιο 11. Συναρτήσεις

Σε αυτό το κεφάλαιο θα συζητήσουμε

·         Τι είναι συναρτήσεις

·         Δημιουργία και εμφάνιση συναρτήσεων από τη γραμμή εντολών

·         Σενάρια με συναρτήσεις

·         Πέρασμα ορισμάτων σε συναρτήσεις

·         Πότε χρησιμοποιούμε συναρτήσεις


11.1. Εισαγωγή

11.1.1. Τι είναι συναρτήσεις;

Οι συναρτήσειςρουτίνες) φλοιού είναι ένας τρόπος να ομαδοποιήσουμε εντολές προς εκτέλεση,και να τις καλούμε με ένα μόνο όνομα από το φλοιό ή από ένα σενάριο. Το όνομα της συνάρτησης πρέπει να είναι μοναδικό στο φλοιό και στο σενάριο. Όλες οι εντολές που συνθέτουν μια συνάρτηση εκτελούνται σαν κανονικές εντολές. Όταν καλούμε μια συνάρτηση απλά με το όνομά της, τότε εκτελούνται οι εντολές που περιλαμβάνονται στη συνάρτηση. Η εκτέλεση γίνεται μέσα στον ίδιο φλοιό, δεν δημιουργείται νέος φλοιός για τη διερμηνεία των εντολών.

Οι εσωτερικές εντολές προηγούνται των συναρτήσεων στην αναζήτηση εντολών από τον φλοιό. Οι σωετρικές εντολές είναι: break, :, ., continue, eval, exec, exit, export, readonly, return, set, shift, trap and unset.


11.1.2. Σύνταξη συναρτήσεων

Οι συναρτήσεις έχουν τη σύνταξη

function FUNCTION { COMMANDS; }

ή

FUNCTION () { COMMANDS; }

Και οι δύο μορφές ορίζουν τη συνάρτηση με το όνομα FUNCTION. Η χρήση της εσωτερικής εντολής function είναι προαιρετική. Αν όμως δεν χρησιμοποιηθεί απαιτούνται παρανθέσεις.

Οι εντολές που εμφανίζονται μεταξύ των αγκυλών αποτελούν το σώμα της συνάρτησης. αυτές οι εντολές εκτελούνται όποτε καλείται η FUNCTION ως εντολή. Η κατάσταση εξόδου της τελευταίας εντολής αποτελεί τη κατάσταση εξόδου της συνάρτησης.

Note

Συνηθισμενα λάθη

 

Οι αγκύλες πρέπει να ξεχωρίζουν από το σώμα με κενά, αλλιώς διερμηνεύονται λανθασμένα.

Το σώμα μιας συνάρτησης πρέπει να τελειώνει με ";" ή αλλαγή γραμμής.


11.1.3. Παράμετροι θέσης σε συναρτήσεις

Οι συναρτήσεις είναι σαν μίνι-σενάρια: μπορούν να δεχτούν παραμέτρους, να έχουν ιδιωτικές (τοπικές) μεταβλητές (μέσω της εσωτερικής εντολής local) μπορούν να επιστρέψουν τιμές στο φλοιό που τις κάλεσε.

Μια συνάρτηση έχει ένα σύστημα διερμηνείας παραμέτρων θέσης. Όμως, οι παράμετροι θέσης της συνάρτησης δεν είναι οι ίδιες με αυτές που δέχεται μια εντολή ή ένα σενάριο.

Κατά την εκτέλεσξ μιας συνάρτησης, τα ορίσματα της συνάρτησης γίνονται παράμετροι θέσης της συνάρτησης. Η ειδική παράμετρος # που επεκτείνεται στον αριθμό των παραμέτρων θέσης ενημερώνεται γι' αυτή την αλλαγή. Η παράμετρος θέσης 0 μένει αμετάβλητη. Η μεταβλητή ου Bash FUNCNAME λαμβάνει το όνομα της συνάρτησης κατά την εκτέλεσή της.

Αν η εσωτερική εντολή return εκτελεστεί σε μια συνάρτηση, η συνάρτηση τερματίζει και η εκτέλεση συνεχίζεται από την εντολή του σεναρίου αμέσως μετά τη συνάρτηση. Μετά το τερατισμό της συνάρτησης οι τιμές των παραμέτρων θέσης και της ειδικής παραμέτρου # επανέρχονται στην πρότερη τιμή τους. Αν η return έχει κάποιο αριθμητικό όρισμα, αυτό επιστρέφεται ως κωδικός κατάστασης. Ένα απλό παράδειγμα:

 
[lydia@cointreau ~/test] cat showparams.sh
#!/bin/bash
                                                                                
echo "This script demonstrates function arguments."
echo
                                                                                
echo "Positional parameter 1 for the script is $1."
echo
                                                                                
test ()
{
echo "Positional parameter 1 in the function is $1."
RETURN_VALUE=$?
echo "The exit code of this function is $RETURN_VALUE."
}
                                                                                
test other_param
 
[lydia@cointreau ~/test] ./showparams.sh parameter1
This script demonstrates function arguments.
 
Positional parameter 1 for the script is parameter1.
 
Positional parameter 1 in the function is other_param.
The exit code of this function is 0.
 
[lydia@cointreau ~/test]

Σημειώστς οτι η τιμή επιστροφής, ή κωδικός κατάστασης εξόδου, συχνά αποθηκεύεται σε μια μεταβλητή, ώστε να μπορεί να ελεγθεί αργότερα. Τα σενάρια εκκίνησης του συστήματός σας συχνά χρησιμοποιούν αυτή τη τεχνική για να ελέγξουν τη μεταβλητή RETVAL σε μια συνθήκη όπως αυτή:

 
if [ $RETVAL -eq 0 ]; then
        <start the daemon>

Ή σαν αυτό το παράδειγμα από το σενάριο /etc/init.d/amd, όπου χρησιμοποιούνται χαρακτηριστικά βελτιστοποίσηης του Bash's:

 
[ $RETVAL = 0 ] && touch /var/lock/subsys/amd

Η εντολές μετά το && εκτελούνται μόνο αν η συνθήκη είναι αληθής: είναι μια σύντμηση της δομής if/then/fi.

Η τιμή επιστροφής της συνάρτησης συχνά χρησιμοποιείται και ώς κωδικός εξόδου για όλο το σενάριο. Θα βρείτε σενάρια που τελειώνουν με και σαν exit $RETVAL.


11.1.4. Εμφάνιση συναρτήσεων

Όλες οι συναρτήσεις που είναι γνωστές στο τρέχοντα φλοιό εμφανίζονται με την εντολή set χωρίς επιλογές. Οι συναρτήσεις διατηρούνται μετά τη χρήση τους, εκτός αν αφαιρεθούν με το unset. Η εντολή which επίσης εμφανίζει συναρτήσεις (σε ορισμένες εκδόσεις του Linux):

 
[lydia@cointreau ~] which zless
zless is a function
zless ()
{
    zcat "$@" | "$PAGER"
}
 
[lydia@cointreau ~] echo $PAGER
less

Αυτή η συνάρτηση είναι τυπική των σεναρίων και συναρτήσεων που βρίσκονται στο σύστημά σας (μπορείτε να βρείτε πολλά παραδείγματα στους καταλόγους των εκτελεσίμων του συστήματος). Οι συναρτήσεις είναι πιο ευέλικτες από τα ψευδώνυμα.

Να μια συνάρτηση για τους χρήστες του DOS:

 
dir ()
{
    ls -F --color=auto -lF --color=always "$@" | less -r
}

11.2. Παραδείγματα συναρτήσεων σε σενάρια

11.2.1. Ανακύκλωση

Υπάρχουν πολλά σενάρια στο σύστημά σας που χρησιμοποιούν συναρτήσεις με ένα δομημένο τρόπο για τη διαχείριση διαφόρων εντολών. Σε μερικά συστήματα Linux, λόγου χάρη, θα βρείτε το αρχείο ορισμών συναρτήσεων /etc/rc.d/init.d/functions, που περιέχει συναρτήσεις που χρησιμοποιούνται από όλα τα σενάρια εκκίνησης. Αυτό επιτρέπει την ανακύκλωση συναρτήσεων. Ένα παράδειγμα από αυτό το αρχείο είναι η συνάρτηση checkpid:

 
# Check if $pid (could be plural) are running
checkpid() {
        local i
 
        for i in $* ; do
                [ -d "/proc/$i" ] && return 0
        done
        return 1
}

Αυτή η συνάρτηση επαναχρησιμοποιείται σε πολλά σενάρια. Η συνάρτηση daemon, για παράδειγμα,χρησιμοποιείται από τη πλειοψηφία των σεναρίων εκκίνησηςδιεργασιών διακομιστών.


11.2.2. Ρύθμιση διαδρομής

Αυτό το τμήμα ίσως μπορεί να βρεθεί στο αρχείο /etc/profile. Η συνάρτηση pathmunge ορίζεται και χρησιμοποιείται για να ορίσει τη διαδρομή για το root και άλλων χρηστών:

 
pathmunge () {
        if ! echo $PATH | /bin/egrep -q "(^|:)$1($|:)" ; then
           if [ "$2" = "after" ] ; then
              PATH=$PATH:$1
           else
              PATH=$1:$PATH
           fi
        fi
}
 
# Path manipulation
if [ `id -u` = 0 ]; then
        pathmunge /sbin
        pathmunge /usr/sbin
        pathmunge /usr/local/sbin
fi
 
pathmunge /usr/X11R6/bin after
 
unset pathmunge

Η συνάρτηση λαμβάνει ως πρώτο της όρισμα ένα όνομα διαδρομής. Αν το όνομα διαδρομής δεν υπάρχει ήδη , τότε προστίθεται. Το δεύτερο όρισμα στη συνάρτηση ορίζει αν η νέα διαδρομή θα προστεθεί στην αρχή ή στο τέλος της τρέχουσας τιμής της PATH.

Στους απλούς χρήστες προστίθεται μόνο το /usr/X11R6/bin, ενώ στο root προστίθενται μερικές ακόμη διαδρομές που εντολές συστήματςος. Στο τέλος ο ορισμός ακυρώνεται (δεν διατηρείται).


11.2.3. Απομακρυσμένα εφεδρικά αντίγραφα

Το παράδειγμα που ακολουθεί είναι αυτό που χρησιμοποιώ για να πάρω εφεδρικά αντίγραφα των σημειώσεών μου. Χρησιμοποιεί κλειδιά SSH για την απομακρθσμένη σύνδεση. Ορίζονται δύο συναρτήσεις, η buplinux και η bupbash, που κάθε μια δημιουργεί ένα αρχείο .tar, το οποίο στη συνέχεια συμπιέζεται και αποστέλεται σε απομακρυσμένο διακομιστή. Μετά από αυτά, το τοπικό αντίγραφο διαγράφεται.

Τη Κυριακή εκτελείτια μόνο η bupbash.

 
#/bin/bash
 
LOGFILE="/nethome/tille/log/backupscript.log"
echo "Starting backups for `date`" >> "$LOGFILE"
 
buplinux()
{
DIR="/nethome/tille/xml/db/linux-basics/"
TAR="Linux.tar"
BZIP="$TAR.bz2"
SERVER="rincewind"
RDIR="/var/www/intra/tille/html/training/"
 
cd "$DIR"
tar cf "$TAR" src/*.xml src/images/*.png src/images/*.eps
echo "Compressing $TAR..." >> "$LOGFILE"
bzip2 "$TAR"
echo "...done." >> "$LOGFILE"
echo "Copying to $SERVER..." >> "$LOGFILE"
scp "$BZIP" "$SERVER:$RDIR" > /dev/null 2>&1
echo "...done." >> "$LOGFILE"
echo -e "Done backing up Linux course:\nSource files, PNG and EPS images.\nRubbish removed." >> "$LOGFILE"
rm "$BZIP"
}
 
bupbash()
{
DIR="/nethome/tille/xml/db/"
TAR="Bash.tar"
BZIP="$TAR.bz2"
FILES="bash-programming/"
SERVER="rincewind"
RDIR="/var/www/intra/tille/html/training/"
 
cd "$DIR"
tar cf "$TAR" "$FILES"
echo "Compressing $TAR..." >> "$LOGFILE"
bzip2 "$TAR"
echo "...done." >> "$LOGFILE"
echo "Copying to $SERVER..." >> "$LOGFILE"
scp "$BZIP" "$SERVER:$RDIR" > /dev/null 2>&1
echo "...done." >> "$LOGFILE"
 
echo -e "Done backing up Bash course:\n$FILES\nRubbish removed." >> "$LOGFILE"
rm "$BZIP"
}
 
DAY=`date +%w`
 
if [ "$DAY" -lt "2" ]; then
  echo "It is `date +%A`, only backing up Bash course." >> "$LOGFILE"
  bupbash
else
  buplinux
  bupbash
fi
 
 
echo -e "Remote backup `date` SUCCESS\n----------" >> "$LOGFILE"

Το σενάριο αυτό εκτελείται από το cron, δηλαδή χωρίς παρέμβαση χρήστη, έτσι ανακατευθύνουμε το πρότυπο σφάλμα της εντολής scp στο /dev/null.

Θα μπορούσαμε να συνδυάσουμε όλα τα βληματα σε μια εντολή όπως

tar c dir_to_backup/ | bzip2 | ssh server "cat > backup.tar.bz2"

Όμως, αν ενδιαφέρεστε για τα ενδιάμεσα αποτελέσματα, που μπορούν να ανακληθούν σε περίπτωση αστοχίας, και, γιενικά, αν θέλετε να ξέρετε τι γίνεται, καλύτερα να αποφεύγετε την υπερβολική συμπύκνωση.

Η έκφραση

command &> file

ισοδυναμεί με

command > file 2>&1


11.3. Περίληψη

Οι συναρτήσεις προσφέρουν ακόμη ένα τρόπο ομαδοποίησης εντολών που εκτελούνται αρκετές φορές. Ότνα εκτελείται μια συνάρτηση, οι παράμετροι θέσης είναι αυτές της συνάρτησης, Όταν η συνάρτηση σταματά, επανέρχονται οι παράμετροι του σεναρίου ή της εντολής που την κάλεσε. Οι συναρτήσεις είναι σαν μινι-σενάρια, και δημιουργούν και επιστρέφουν κωδικούς κατάστασης.

Αν και το κεφάλαιο είναι σύντομο, καλύπτει οτι σημαντικό απαιτείται για να επιτύχουμε τον τελικό στόχο κάθε προγραμματιστή, το περιορισμό της περιττής δουλειάς.


11.4. Ασκήσεις

Να μερικά χρήσιμα πράγματα που μπορείτε να κάνετα με τις συναρτήσεις:

1.      Προσθέστε μια συνάρτηση στο αρχείο ~/.bashrc που να αυτοματοποιεί την εκτύπωση των σελίδων εγχειριδίου. Το αποτέλεσμα πρέπει να είναι να εισάγετε μια εντολή στη μορφή printman <command>, με την οποία η κατάλληλες σελίδες να πηγαίνουν στον εκτυπωτή σας. Ελέξτε τη λειτουργία της με τη βοήθεια ενός ψευδο-εκτυπωτή.

Σαν επιλέον χαρακτηριστικό, προσθέστε τον αριθμό ενότητας της σελίδας εγχειριδίου που θέλετε να τυπωθεί.

2.      Δημιουργείστε ένα υπο-κατάλογο στον οικείο σας κατάλογο όπου να αποθηκέυετε ορισμούς συναρτήσεων. Τοποθευήστε μερικούς ορισμούς συναρτήσεων στο κατάλογο. Στη συνέχεια αυτές οι συναρτήσεις θα πρέπει να εισάγονται στο περιβάλλον φλοιού σας μέσω του αρχείου ~/.bashrc.


Κεφάλαιο 12. Λήψη σημάτων

Σε αυτό το κεφάλαιο, θα συζητήσουμε τα παρακάτω θέματα:

·         Διαθέσιμε σήματα

·         Χρήση σημάτων

·         Χρήση της δήλωσης trap 

·         Πώς να αποτρέψετε τη διακοπή των προγραμμάτων σας από χρήστες


12.1. Σήματα

12.1.1. Εισαγωγή

12.1.1.1. Εύρεση της σελίδας εγχειριδίου των σημάτων

Το σύστημά σας περιέχει μια σελίδα εγχειριδίου με όλα τα διαθέσιμα σήματα, αλλά ανάλογά με την έκδοση του λειτουργικού σας μπορεί να βρίσκεται σε διαφορετική θέση. Στα περισσότερα συστήματα Linux, η σελίδα είναι η man 7 signal. Αν αμφιβλαλλετε, εντοπίστε τη σελίδα με μια εντολή όπως

man -k signal | grep list

ή

apropos signal | grep list

Τα ονόματα των σημάτων μπορούν να βρεθούν με την εντολή kill -l.


12.1.1.2. Σήματα προς τον φλοιό Bash 

Αν δεν υπάρχουν παγίδες (traps), ένας διαλογικός φλοιός Bash αγνοεί τα σήματα SIGTERM και SIGQUIT. Το SIGINT λαμβάνεται και αν είναι ενεργός ο έλεγχος εργασιών, επίσης αγνοούνται τα  SIGTTIN, SIGTTOU και SIGTSTP. Οι εντολές που εκτελούνται σαν αποτέλεσμα αντικατάσταση εντολών, επίσης αγνοούν αυτά τα σήματα, όταν δημιουργούνται από το πληκτρολόγιο.

Το SIGHUP ως προεπιλογή τερματίζει ένα φλοιό. Ένας διαλογικός φλοιός θα στείλει ένα σήμα SIGHUP προς όλες τις εργασίες, εκτελούμενες ή σταματημένες, δείτε τη τεκμηρλιωση της εσωτερικής εντολής disown αν θέλετε να αναιρέσετ αυτή τη προεπιλεγμένη συμπεριφορά. Η επιλογή huponexit της εσωτερικής εντολής shopt τερματίζει όλες τις διεργασίες με την λήψη ενός σήματος SIGHUP.


12.1.1.3. Αποστολή σημάτων μέσω του φλοιού

Τα ακόλουθα σήματα μπορούν να αποσταλούν μέσω του φλοιού Bash:

Πίνακας 12-1. Σήματα ελέγχου στο Bash

Τυπικός συνδυασμός πλήκτρων

Σημασία

Ctrl+C

Το σήμα διακοπής, στέλενει SIGINT στην εργασία που εκτελείται στο προσκήνιο.

Ctrl+Y

Ο χαρακτήρας καθυστερημένης αναστολής (delayed suspend). Προκαλεί το σταμάτημα μιας εκτελούμενης διεργασίας, όταν προσπαθεί να διαβάσει είσοδο από το πληκτρολόγιο. Ο έλεγχος επιστρέφει στο φλοιό, ο χρήστης μπορεί να τερματίσει τη διεργασία ή να τη θέσει στο προσκήνιο είτε στο παρασκήνιο. Το χαρακτηριστικό αυτό δεν διατίθεται σε όλες τις εκδόσεις.

Ctrl+Z

Το σήμα αναστολής (suspend), στέλνει ένα SIGTSTP σε ένα εκτελούμενο πρόγταμμα, και έτσι το σταματά και επιστρέφει τον έλεγχο στο φλοιό.

Note

Ρυθμίσεις τερματικού

 

Ελέγξτε τις ρυθμίσεις του stty. Συνήθως η αναστολή και συνέχιση είναι ακυρωμένες στα "σύγχρονα" τερματικά. Το τυπικό xterm υποστηιζει τα Ctrl+S και Ctrl+Q ως προεπιλογή


12.1.2. Χρήση των σημάτων με τη kill

Οι περισσότεροι σύγχρονοι φλοιοί, όπως και το Bash, έχει μια εσωτερική εντολή kill. Το Bash, δέχεται ως επιλογές τόσο τα ονόματα όσο και τους αριθμούς των σημάτων, ενώ επιλογές μπορεί να είναι εργασίες και ID διεργασιών. Η κατάσταση εξόδου μπορεί να καταγραφεί με την επιλογή -l: μηδέν αν τουλάχιστο ένα σήμα σταλεί μια επιτυχία, μη-μηδενικό αν συμβεί κάποιο σφάλμα.

Η εντολή kill από το /usr/bin, επιτρέπει περισσότερες επιλογές, όπως το τερματισμό διεργασιών με ID χρήστη διαφορετικό από το δικό σας και ορισμό διεργασίας με όνομα, όπως οι pgrep και pkill.

Και οι δύο εντολές kill ως προεπιλογή στέλνουν το σήμα TERM.

Αυτή είναι μια λίστα με τα συνηθισμένα σήματα:

Πίνακας 12-2. Συνηθισμένα σήματα kill 

Όνομα σήματος

Τιμή σήματος

Αποτέλεσμα

SIGHUP

1

Hangup

SIGINT

2

Interrupt from keyboard

SIGKILL

9

Kill signal

SIGTERM

15

Termination signal

SIGSTOP

17,19,23

Stop the process

Note

SIGKILL και SIGSTOP

 

Τα SIGKILL και SIGSTOP δεν μπορούν να μη ληφθούν, εμποδιστούν ή αγνοηθούν.

Όταν τερματίζουμε διεργασία ή σειρά διεργασιών, είναι λογικό να ξεκινούμε από το λιγότερο επικίνδυνο σήμα, το SIGTERM. Έτσι τα προγράμματα που ενδιαφέρονται για ένα τακτοποιημένο τερματισμό έχουν την ευκαιρία να ακολουθήσουν τις διαδικασίες που έχουν προβλεφθεί για τη λήψη σήματος SIGTERM, όπως καθαρισμός προσωρινών αρχείων και κλείσιμο αρχείων. Αν στείλετε άνα σήμα SIGKILL σε μια διεργασία, της αφαιρείτε κάθε περιθώριο για οργανωμένο τερματισμό, κάτι που μπορέι να έχει διάφορες συνέπειες.

Αν δεν πετύχει ο απλός τερματισμός, τότε τα σήματα INT ή KILL ίσως είναι ο μόνος τρόπος. Για παράδειγμα, όταν μια διεργασία δεν πεθαίνει με το Ctrl+C, τότε χρησιμοποιούμε την εντολή kill -9 στο ID της διεργασίας:

 
maud: ~> ps -ef | grep stuck_process
maud    5607   2214  0 20:05 pts/5    00:00:02 stuck_process
 
maud: ~> kill -9 5607
 
maud: ~> ps -ef | grep stuck_process
maud    5614    2214 0 20:15 pts/5    00:00:00 grep stuck_process
[1]+ Killed            stuck_process

Όταν ένα πρόγραμμα εκκινεί πολλά στιγμιότυπα, η εντολή killall ίσως είναι ευκολότερη. Λαμβάνει τις ίδιες επιλογές με την εντολή kill αλλά εφαρμόζεται σε όλα τα στιγμιότυπα ενός προγράμματος.  Επειδή είναι ιδιαίτερα ισχυρή ελέγξτε τη καλά πριν από τη χρήση σε σενάρια.


12.2. Παγίδες

12.2.1. Γενικά

'Ισως να υπάρχουν περιπτώσεις που δεν θέλετε να διακοπεί το σενάριό σας από άκαιρες πληκτρολογήσεις. Η εντολή trap συλλαμβάνει αυτές τις πληκτρολογήσεις και μπορεί να προγραμματιστεί ώστε να εκτελεί μια σειρά εντολών με τη λήψη των σημάτων αυτών.

Η σύνταξη της trap είναι απλή:

trap [COMMANDS] [SIGNALS]

Η trap συλλαμβάνει τα σήματα που αναφέρονται στη λίστα SIGNALS, που μπορεί να είναι ονόματα με ή χωρίς το πρόθεμα SIG, ή αριθμοί σημάτων. Αν ένα σήμα είναι 0 ή EXIT, η λίστα εντολών COMMANDS εκτελείται όταν ο φλοιός τερματίζει. Αν ένα από τα σήματα είναι το DEBUG, η λίστα εντολών COMMANDS εκτελέιται με κάθε εντολή. Ένα σήμα μπορεί να οτιστεί σαν ERR. Σε αυτή τη περίπτωση οι εντολές COMMANDS εκτελούνται κάθε φορά που μια εντολή τερματίζει με μη-μηδενικό κωδικό κατάστασης. Σημειώστε οτι αυτές οι εντολές δεν θα εκτελεστούν αν η μη-μηδενική κατάσταση έλθει από μια δήλωση if είτε από βρόχο while ή until. Το ίδιο ισχύει για τα αποτελέσματα λογικών AND (&&) ή OR (||) ή αν η κατάσταση εξόδου αντιστραφεί με τον τελεστή ! .

Ο κωδικός κατάστασης της εντολής trap είναι μηδέν εκτός αν βρεθεί άκυρος κωδικός σήματος. Η εντολή trap δέχετα μερικές επιλογές, που μπορελιτε να βρελιτε στης σελίδες πληροφοριών του Bash.

Να ένα πολυ απλό παράδειγμα, που συλλαμβάνει το Ctrl+C του χρήστη και εμφανίζει ένα μήνυμα. Αν προσπαθήσετε να τερματίσετε αυτί το σενάριο χωρς να ορίσετετ το σήμα KILL, δεν θα γλινει τίποτε:

 
#!/bin/bash
# traptest.sh
 
trap "echo Booh!" SIGINT SIGTERM
echo "pid is $$"
 
while :                # This is the same as "while true".
do
        sleep 60       # This script is not really doing anything.
done

12.2.2. Πως εξηγεί τις παγίδες το Bash 

Όταν το Bash λαμβάνει ένα σήμα για το οποίο έχει τεθεί μια παγίδα, ενώ εκτελείται μια εντολή, η παγίδα δεν θα εκτελεστεί μέχρι να ολοκληρωθεί η εκτέλεση της εντολής. Όταν το Bash περιμένει την ολοκλήρωση μια εντολής μέσω της εσωτερικής εντολής wait, η λήψη ενός σήματος για το οποίο έχει τεθεί μια παγίδα, η wait επιστρέφει άμεσα με κωδικό εξόδου μεγαλύτερο του 128, και μέσως μετά εκτελείται η παγίδα.


12.2.3. Παραδείγματα

12.2.3.1. Ανίχνευση χρήσης μεταβλητής

Κατά την εκσφαλμάτωση μεγαλύτερων σεναρίων, ίσως να χρειαστεί να αποδόσετε σε κάποια μεταβλητή την ιδότητα του ίχνους (trace) και να παγιδέυσετε τα μηνύματα DEBUG γι' αυτή τη μεταβλητή. Τυπικά θα δηλώσετε τη μεταβλητή ως VARIABLE=value. Αν η δήλωση αντικατασταθεί με αυτή που ακολουθεί, κάθε χρήση της μεταβλητής θα ανιχνεύεται, έτσι ώστε μπορείτε να πάρετε αρκετές πληροφορίες για τη λειτουργία του σεναρίου:

 
declare -t VARIABLE=value
 
trap "echo VARIABLE is being used here." DEBUG
 
# rest of the script

12.2.3.2. Απομάκρυνση αχρήστων κατά την έξοδο

Η εντολή whatis βασίζεται σε μια βάση δεδομένων που κτίζεται τακτικά με το σενάριο makewhatis.cron μέσω του cron:

 
#!/bin/bash
 
LOCKFILE=/var/lock/makewhatis.lock
 
# Previous makewhatis should execute successfully:
 
[ -f $LOCKFILE ] && exit 0
 
# Upon exit, remove lockfile.
 
trap "{ rm -f $LOCKFILE ; exit 255; }" EXIT
 
touch $LOCKFILE
makewhatis -u -w
exit 0

12.3. Περίληψη

Τα σήματα αποστέλονται στις διεργασίες με την εντολή kill ή με συνδυασμούς πληκτρολογήσεων. Αυτά τα σήματα μπορούν να συλληφθούν, και με τη βοήθεια της εσωτερικής εντολής trap μπορούν να εκτελεστούν διάφορες ενέργειες.

Μερικά προγράμματα αγνοούν τα σήματα. Το μόνο σήμα ποου δεν μπορεί να αγνοηθεί είναι το KILL (9).


12.4. Ασκήσεις

Δύο πρακτικά παραδείγματα:

1.      Δημιουργείστε ένα σενάριο που γράφει μια εικόμα εκκίνησης (boot image) σε μια δισκέτα με την εντολή dd. Αν ο χρήστης προσπαθήσει να διακόψει το σενάριο με Ctrl+C, εμφανίστε άνα μήνυμα που να λέει οτι η διακοπή θα καταστήσει τη δισκέτα άχρηστη.

2.      Γράψτε ένα πρόγραμμα που αυτοματοποιεί την εγκατάσταση ενός πακέτου της επιλογής σας. Το πακέτο πρέπει να μεταφορτωθεί μέσω του Διαδικτύου, να αποσυμπιεστεί, να απο-αρχειθετηθεί και στη συνέχεια να μεταγλωττιστεί (επιλέξτε τις κατάλληλες ενέργειες, ανάλογα με το πακέτο). Η τελική εγκατάσταση του πακέτου (μόνο αυτή) θα πρέπει να μη μπορεί να διακοπεί.


Παράρτημα Α. Χαρακτηριστικά φλοιών

Αυτό το παράρτημα παρέχει μια επισκόπηση των κοινών και των διαφορετικών χαρακτηριστικών των βασικών φλοιών.


Α.1. Κοινά χαρακτηριστικά

Τα παρακάτω χαρακτηριστικά είναι κοινά σε κάθε φλοιό. Σημειώστε οτι οι εντολές τερματισμού, αναστολής, jobs, bg και fg είναι διαθέσιμες μόνο σε συστήματα που υποστηρίζουν έλεγχο εργασιών.

Πίνακας Α-1. Κοινά χαρακτηριστικά φλοιών

Εντολή

Σημασία

>

Ανακατεύθυνση εξόδου

>>

Προσάρτηση σε αρχείο

<

Ανακατεύθυνση εισόδου

<<

Προσάρτηση εισόδου

|

Σωλήνωση εξόδου

&

Εκτέλεση διεργασίας στο παρασκήνιο

;

Διαχωρισμός εντολών στην ίδια γραμμή

*

Ταύτιση οποιουδήποτε χαρακτήρα σε όνομα αρχείου

?

Ταύτιση ενός χαρακτήρα σε όνομα αρχείου

[ ]

Ταύτιση των χαρακτήρων που περιλαμβάνονται στις αγκύλες

( )

Εκτέλεση σε υπο-φλοιό

` `

Υποκατάσταση εξόδου της εντολής που βρίσκεται μέσα στις εισαγωγικά

" "

Μερική αναπαραγωγή (επιτρέπει μεταβλητές και επέκταση εντολών)

' '

Πλήρης αναπαραγωγή (μη επέκταση)

\

Αναπαραγωγή επόμενου χαρακτήρα

$var

Τιμή μεταβλητής var

$$

Αριθμός διεργασίας

$0

Όνομα εντολής

$n

n-ισοτό όρισμα (n από 0 έως 9)

$*

Όλα τα ορίσματα σε μια απλή λέξη

#

Αρχή σχολίου

bg

Εκτέλεση στο παρασκήνιο

break

Έξοδος από βρόχο

cd

Αλλαγή καταλόγων

continue

Συνέχιση βρόχου

echo

Εμφάνιση εξόδου

eval

Αποτίμηση ορισμάτων

exec

Εκτέλεση σε νέο φλοιό

fg

Εκτέλεση στο προσκήνιο

jobs

Εμφάνιση ενεργών εργασιών

kill

Τερματισμός εκτελούμενων εργασιών

newgrp

Αλλαγή σε νέα ομάδα

shift

Shift positional parameters

stop

Αναστολή εργασίας παρασκηνίου

suspend

Αναστολή εργασίας προσκηνίου

time

Χρονισμός εντολής

umask

Ρύθμιση αδειών αρχείου

unset

Διαγραφή μεταβλητής ή ορισμών συναρτήσεων

wait

Αναμονή τερματισμού εργασίας παρασκηνίου



Α.2. Διαφορετικά χαρακτηριστικά

Ο παρακάτω πίνακας δείχνει τις κύριες διαφορές μεταξύ του πρότυπου φλοιού shell (sh), Bourne Again SHell (bash), Korn shell (ksh) και του C shell (csh).

Note

Συμβατότητα φλοιών

 

Αφού το Bourne Again SHell είναι υπερσύνολο του sh, όλες οι εντολές του sh θα εκτελεστούν και στο bash – αλλά όχι το αντίστροφο. Το bash έχει πολύ περισσότερα δικά του χαρακτηριστικά, και, όπως δείχνει ο παρακάτω πίνακας,έχει ενσωματώσει χαρακτηριστικά και άλλων φλοιών.

Αφού το Turbo C shell είναι υπερσύνολο του του csh, όλες οι εντολές csh θα δουλέψουν στο tcsh, αλλά όχι το αντίστροφο.

Πίνακας Α-2. Διαφορετικά χαρακτηριστικά φλοιών

sh

bash

ksh

csh

Σημασία/Ενέργεια

$

$

$

%

Προ-επιλεγμένη προτροπή

 

>|

>|

>!

Επιβολή ανακατεύθυνσης

> file 2>&1

&> file or > file 2>&1

> file 2>&1

>& file

Ανακατεύθυνση stdout και stderr στο file

 

{ }

 

{ }

Επέκταση στοιχείων στη λίστα

`command`

`command` or $(command)

$(command)

`command`

Αντικατάσταση εξόδου της εντολής command

$HOME

$HOME

$HOME

$home

Οικείος κατάλογος

 

~

~

~

Σύμβολο οικείου καταλόγου

 

~+, ~-, dirs

~+, ~-

=-, =N

Access directory stack

var=value

VAR=value

var=value

set var=value

Ανάθεση τιμής σε μεταβλητή

export var

export VAR=value

export var=val

setenv var val

Ανάθεση τιμής σε μεταβλητή περιβάλλοντος

 

${nnnn}

${nn}

 

Προσπέλαση περισσότερων από 9 ορισμάτων

"$@"

"$@"

"$@"

 

Όλα τα ξεχωριστά ορίσματα ως ξεχωριστές λέξεις

$#

$#

$#

$#argv

Αριθμός ορισμάτων

$?

$?

$?

$status

Κατάσταση εξόδου της εντολής που εκελέστηκε πιο πρόσφατα

$!

$!

$!

 

Το PID για τη πιο πρόσφατη διεργασία υποβάθρου

$-

$-

$-

 

Τρέχουσες επιλογές

. file

source file or . file

. file

source file

Διάβασε εντολές από αρχείο

 

alias x='y'

alias x=y

alias x y

Συνώνυμο x για εντολή y

case

case

case

switch or case

Πολλαπλή επιλογή

done

done

done

end

Τερματισμός επανάληψης

esac

esac

esac

endsw

Τέλος case ή switch

exit n

exit n

exit n

exit (expr)

Έξοδος με αριθμό κατάστασης

for/do

for/do

for/do

foreach

Επανάληψη through variables

 

set -f , set -o nullglob|dotglob|nocaseglob|noglob

 

noglob

Ignore substitution characters for filename generation

hash

hash

alias -t

hashstat

Display hashed commands (tracked aliases)

hash cmds

hash cmds

alias -t cmds

rehash

Remember command locations

hash -r

hash -r

 

unhash

Forget command locations

 

history

history

history

Εμφάνιση προηγούμενων εντολών

 

ArrowUp+Enter or !!

r

!!

Επανάληψη τελευταίας εντολής

 

!str

r str

!str

Επανάληψη της τελευταίας εντολής που αρχίζει από "str"

 

!cmd:s/x/y/

r x=y cmd

!cmd:s/x/y/

Αντικατάσταση "x"με "y" στη πιο πρόσφατη εντολή που ξεκινά με "cmd", και εκτέλεση.

if [ $i -eq 5 ]

if [ $i -eq 5 ]

if ((i==5))

if ($i==5)

Ενδεικτική συνθήκη if

fi

fi

fi

endif

Τέλος if

ulimit

ulimit

ulimit

limit

Όριο πόρου

pwd

pwd

pwd

dirs

Εμφάνιση τρέχοντος καταλόγου

read

read

read

$<

Ανάγνωση από τερματικό

trap 2

trap 2

trap 2

onintr

Αγνόηση διακοπών

 

unalias

unalias

unalias

Αφαίρεση συνωνύμων

until

until

until

 

Αρχή βρόχου until

while/do

while/do

while/do

while

Αρχή βρόχου while

Το Bourne Again SHell έχει πολύ περισσότερα χαρακτηριστικά από αυτά που εμφανίζονται εδώ. Ο πίνακας σας δίνει μια ιδέα πως αυτός ο φλοιός ενσωματώνει καλές ιδέες από άλλους φλοιούς: στη στήλη του bash .δεν υπάρχουν κενά. Περισσότερες πληροφορίες στις σελίδες τεκμηρίωσης του Bash, στην ενότητα "Bash Features".

Γενικότερα:

Πρέπει να διαβάσετε τουλάχιστο ένα εγχειρίδιο, αυτό του φλοιού. Η καλύτερη επιλογή είναι το info bash, αφού το bash είναι το καλύτερο για αρχαρίους. Τυπώστε το εγχειρίδιο και διαβάστε το, όποτε έχετε λίγο καιρό.


Appendix B. GNU Free Documentation License

Version 1.1, March 2000

Copyright (C) 2000 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.


B.1. Preamble

The purpose of this License is to make a manual, textbook, or other written document "free" in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.

This License is a kind of "copyleft", which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.

We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.


B.2. Applicability and definitions

This License applies to any manual or other work that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. The "Document", below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as "you".

A "Modified Version" of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.

A "Secondary Section" is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document's overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (For example, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.

The "Invariant Sections" are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License.

The "Cover Texts" are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License.

A "Transparent" copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, whose contents can be viewed and edited directly and straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup has been designed to thwart or discourage subsequent modification by readers is not Transparent. A copy that is not "Transparent" is called "Opaque".

Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML designed for human modification. Opaque formats include PostScript, PDF, proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML produced by some word processors for output purposes only.

The "Title Page" means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, "Title Page" means the text near the most prominent appearance of the work's title, preceding the beginning of the body of the text.


B.3. Verbatim copying

You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and you may publicly display copies.


B.4. Copying in quantity

If you publish printed copies of the Document numbering more than 100, and the Document's license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a publicly-accessible computer-network location containing a complete Transparent copy of the Document, free of added material, which the general network-using public has access to download anonymously at no charge using public-standard network protocols. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.

It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.


B.5. Modifications

You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

A.     Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.

B.     List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has less than five).

C.     State on the Title page the name of the publisher of the Modified Version, as the publisher.

D.     Preserve all the copyright notices of the Document.

E.      Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.

F.      Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.

G.     Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document's license notice.

H.     Include an unaltered copy of this License.

I.        Preserve the section entitled "History", and its title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section entitled "History" in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.

J.       Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the "History" section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.

K.    In any section entitled "Acknowledgements" or "Dedications", preserve the section's title, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.

L.      Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.

M.   Delete any section entitled "Endorsements". Such a section may not be included in the Modified Version.

N.    Do not retitle any existing section as "Endorsements" or to conflict in title with any Invariant Section.

If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

You may add a section entitled "Endorsements", provided it contains nothing but endorsements of your Modified Version by various parties--for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.


B.6. Combining documents

You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice.

The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections entitled "History" in the various original documents, forming one section entitled "History"; likewise combine any sections entitled "Acknowledgements", and any sections entitled "Dedications". You must delete all sections entitled "Endorsements."


B.7. Collections of documents

You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.


B.8. Aggregation with independent works

A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, does not as a whole count as a Modified Version of the Document, provided no compilation copyright is claimed for the compilation. Such a compilation is called an "aggregate", and this License does not apply to the other self-contained works thus compiled with the Document, on account of their being thus compiled, if they are not themselves derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one quarter of the entire aggregate, the Document's Cover Texts may be placed on covers that surround only the Document within the aggregate. Otherwise they must appear on covers around the whole aggregate.


B.9. Translation

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License provided that you also include the original English version of this License. In case of a disagreement between the translation and the original English version of this License, the original English version will prevail.


B.10. Termination

You may not copy, modify, sublicense, or distribute the Document except as expressly provided for under this License. Any other attempt to copy, modify, sublicense or distribute the Document is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.


B.11. Future revisions of this license

The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/.

Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License "or any later version" applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation.


B.12. How to use this License for your documents

To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:

Copyright (c) YEAR YOUR NAME. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. A copy of the license is included in the section entitled "GNU Free Documentation License".

If you have no Invariant Sections, write "with no Invariant Sections" instead of saying which ones are invariant. If you have no Front-Cover Texts, write "no Front-Cover Texts" instead of "Front-Cover Texts being LIST"; likewise for Back-Cover Texts.

If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.


Ευρετήριο

A

ψευδώνυμα (aliases)

Ενότητα 3.5.1

ANSI-C εισαγωγικά (quoting)

Ενότητα 3.3.5

ορίσματα (arguments)

Ενότητα 7.2.1.2

αριθμητική επέκταση (arithmetic expansion)

Ενότητα 3.4.7

αριθμητικοί τελεστές (arithmetic operators)

Ενότητα 3.4.7

πίνακας (array)

Ενότητα 10.2.1

awk

Ενότητα 6.1

awkprogram

Ενότητα 6.1.2

B

bash

Ενότητα 1.2

.bash_login

Ενότητα 3.1.2.2

.bash_logout

Ενότητα 3.1.2.5

.bash_profile

Ενότητα 3.1.2.1

.bashrc

Ενότητα 3.1.2.4

συντάκτης δέσμης (batch editor)

Ενότητα 5.1.1

break

Ενότητα 9.5.1

λογικοί τελεστές (boolean operators)

Ενότητα 7.2.4

φλοιός Bourne (shell)

Ενότητα 1.1.2

επέκταση παρενθέσεων (brace expansion)

Ενότητα 3.4.3

εσωτερικές εντολές (built-in commands)

Ενότητα 1.3.2

C

δηλώσεις case (statements)

Ενότητα 7.2.5

κλάσεις χαρακτήρων (character classes)

Ενότητα 4.2.2.2, Ενότητα 4.3.2

θυγατρική διεργασία (child process)

Ενότητα 1.3.1

συνδυασμένες εκφράσεις (combined expressions)

Ενότητα 7.1.1.1

αντικατάσταση εντολών (command substitution)

Ενότητα 3.4.6

σχόλια (comments)

Ενότητα 2.2.2

συνθήκες (conditionals)

Ενότητα 7.1

αρχεία διαμόρφωσης (configuration files)

Ενότητα 3.1

σταθερές (constants)

Ενότητα 10.1.3

continue

Ενότητα 9.5.2

σήματα ελέγχου (control signals)

Ενότητα 12.1.1.3

δημιουργία μεταβλητών (creating variables)

Ενότητα 3.2.2

csh

Ο φλοιός C, Ενότητα 1.1.2

D

εκσφαλμάτωση σεναρίων (debugging scripts)

Ενότητα 2.3

declare

Ενότητα 10.1.2, Ενότητα 10.2.1

διπλά εισαγωγικά (double quotes)

Ενότητα 3.3.4

E

echo

Ενότητα 1.5.5, Ενότητα 2.1.2, Ενότητα 2.3.2, Ενότητα 8.1.2

συντάκτες (editors)

Ενότητα 2.1.1

else

Ενότητα 7.2.1

emacs

Ενότητα 2.1.1

env

Ενότητα 3.2.1.1

esac

Ενότητα 7.2.5

χαρακτήρες διαφυγής (escape characters)

Ενότητα 3.3.2

ακολουθία διαφυγής (escape sequences)

Ενότητα 8.1.2

/etc/bashrc

Ενότητα 3.1.1.2

/etc/passwd

Ενότητα 1.1.2

/etc/profile

Ενότητα 3.1.1

/etc/shells

Ενότητα 1.1.2

exec

Ενότητα 1.3.1, Ενότητα 8.2.4.2

δικαιώματα εκτέλεσης) execute permissions

Ενότητα 2.1.3

εκτέλεση (execution)

Ενότητα 2.1.3

exit

Ενότητα 7.2.5

κατάσταση εξόδου (exit status)

Ενότητα 7.1.2.1

επέκταση (expansion)

Ενότητα 1.4.1.5, Ενότητα 3.4

export

Ενότητα 3.2.3

εκτεταμένες κανονικές εκφράσεις (extended regular expressions)

Ενότητα 4.1.3

F

περιγραφείς αρχείων (file descriptors)

Ενότητα 8.2.3, Ενότητα 8.2.4.1

επέκταση ονόματος αρχείου (file name expansion)

Ενότητα 3.4.9

εύρεση και αντικατάσταση (find and replace)

Ενότητα 5.2.4

for

Ενότητα 9.1

fork

Ενότητα 1.3.1

functions

Ενότητα 11.1.1

G

gawk

Ενότητα 6.1.1

gawk εντολές (commands)

Ενότητα 6.1.2

gawk πεδία (fields)

Ενότητα 6.2.1

gawk (μορφοποίηση) formatting

Ενότητα 6.2.2

gawk (σενάρια) scripts

Ενότητα 6.2.5

gawk (μεταβλητές) variables

Ενότητα 6.3

gedit

Ενότητα 2.1.1

καθολικές μεταβλητές (global variables)

Ενότητα 3.2.1.1

globbing

Ενότητα 2.3.2

grep

Ενότητα 4.2.1

H

here document

Ενότητα 8.2.4.4

I

if

Ενότητα 7.1.1

init

Ενότητα 1.3.1, Ενότητα 1.5.6

αρχεία εκκίνησης (initialization files)

Ενότητα 3.1

διαχωριστής πεδίων εισόδου (input field separator)

Ενότητα 3.2.4.1, Ενότητα 3.2.5, Ενότητα 6.3

διαλογική σύνταξη (interactive editing)

Ενότητα 5.2

διαλογικά σενάρια (interactive scripts)

Ενότητα 8.1

διαλογικός φλοιός (interactive shell)

Ενότητα 1.2.2.2.1, Ενότητα 1.2.2.2.2, Ενότητα 1.2.2.3.3

κλήση (invocation)

Ενότητα 1.2.2.1

J

K

kill

Ενότητα 12.1.2

killall

Ενότητα 12.1.2

ksh

Korn shell, Ενότητα 1.1.2

L

μήκος μεταβλητής (length of a variable)

Ενότητα 10.3.2

άγκυρες γραμμής (line anchors)

Ενότητα 4.2.2.1

locale

Ενότητα 3.3.6

locate

Ενότητα 2.1.1

λογική ροή (logic flow)

Ενότητα 1.5.4

φλοιός σύνδεσης (login shell)

Ενότητα 1.2.2.2.1

M

menu

Ενότητα 9.6

μεταχαρακτήρες (metacharacters)

Ενότητα 4.1.2

N

ένθετες σηλώσεις if (nested if statements)

Ενότητα 7.2.3

noglob

Ενότητα 2.3.2

μη-διαλογική σύνταξη (non-interactive editing)

Ενότητα 5.3

μη-διαλογικός φλοιός (non-interactive shell)

Ενότητα 1.2.2.2.3

φλοιός μη-σύνδεσης (non-login shell)

Ενότητα 1.2.2.2.2

αριθμητικές συγκρίσεις (numeric comparisons)

Ενότητα 7.1.2.2

O

επιλογές (options)

Ενότητα 3.6.1

διαχωριστής πεδίων εξόδου (output field separator)

Ενότητα 6.3.2.1

διαχωριστής γραμμών εξόδου (output record separator)

Ενότητα 6.3.2.2

P

επέκταση παραμέτρων (parameter expansion)

Ενότητα 3.4.5

PATH

Ενότητα 2.1.2

ταύτιση προτύπων (pattern matching)

Ενότητα 4.3

positionalparams

Ενότητα 3.2.5, Ενότητα 11.1.3

POSIX

Ενότητα 1.2.1

POSIX κατάσταση (mode)

Ενότητα 1.2.2.2.5

βασικές εκφράσεις (primary expressions)

Ενότητα 7.1.1.1

printenv

Ενότητα 3.2.1.1

printf

Ενότητα 1.5.5, Ενότητα 6.3.6

αντικατάσταση διεργασιών (process substitution)

Ενότητα 3.4.8

.profile

Ενότητα 3.1.2.3

προτροπή (prompt)

Ενότητα 3.1.3

Q

χαρακτήρες σε εισαγωγικά (quoting characters)

Ενότητα 3.3

R

ανακατεύθυνση (redirection)

Ενότητα 1.4.1.7, Ενότητα 3.6.2, Ενότητα 8.2.3, Ενότητα 9.4

rbash

Ενότητα 1.2.2.10

read

Ενότητα 8.2.1

readonly

Ενότητα 10.1.3

τελεστές κανονικών εκφράσεων (regular expression operators)

Ενότητα 4.1.2, Ενότητα 5.2, Ενότητα 6.2.4

κανονικές εκφράσεις (regular expressions)

Ενότητα 4.1

απομακρυσμένη κλήση (remote invocation)

Ενότητα 1.2.2.2.6

απομάκρυνση ψευδονύμων (removing aliases)

Ενότητα 3.5.2

δεσμευμένες μεταβλητές (reserved variables)

Ενότητα 3.2.4

return

Ενότητα 11.1.3

S

sed

Ενότητα 5.1

sed εντολές σύνταξης (editing commands)

Ενότητα 5.1.2

sed επιλογές (options)

Ενότητα 5.1.2

sed σενάρια (script)

Ενότητα 5.3.2

select

Ενότητα 9.6

set

Ενότητα 3.2.1.2, Ενότητα 3.6.1, Ενότητα 11.1.4

shift

Ενότητα 9.7

σήματα (signals)

Ενότητα 12.1.1

απλά εισαγωγικά (single quotes)

Ενότητα 3.3.3

source

Ενότητα 2.1.3

ειδικές παράμετροι (special parameters)

Ενότητα 3.2.5

ειδικές μεταβλητές (special variables)

Ενότητα 3.2.5

πρότυπο σφάλμα (standard error)

Ενότητα 8.2.3.1

πρότυπη είσοδος (standard input)

Ενότητα 8.2.3.1

πρότυπη έξοδος (standard output)

Ενότητα 8.2.3.1

συμβολοσειρά σύγκριση (string comparisons)

Ενότητα 7.1.2.3

stty

Ενότητα 12.1.1

υπο-menu (submenu)

Ενότητα 9.6.2

υπο-φλοιός (subshell)

Ενότητα 2.2.1

αντικατάσταση (substitution)

Ενότητα 10.3.3.1, Ενότητα 10.3.3.3

στμβολοσειρά τμήμα (substring)

Ενότητα 10.3.3.2

σύνταξη (syntax)

Ενότητα 1.4.1.1

T

tcsh

Ενότητα 1.1.2

ορολογία (terminology)

Ενότητα 1.5.3

then

Ενότητα 7.1.1.2

επέκταση περισπωμένης (tilde expansion)

Ενότητα 3.4.4

μετατροπή μεταβλητών (transformation of variables)

Ενότητα 10.3.3

παγίδες (traps)

Ενότητα 12.2.1

true

Ενότητα 9.2.2.2

U

unalias

Ενότητα 3.5.1, Ενότητα 3.5.2

unset

Ενότητα 3.2.2, Ενότητα 10.2.3, Ενότητα 11.1.4

until

Ενότητα 9.3

είσοδος χρήστη (user input)

Ενότητα 8.2.1, Ενότητα 8.2.2

μηνύματα χρήστη (user messages)

Ενότητα 8.1.1

V

μεταβλητές (variables)

Ενότητα 3.2, Ενότητα 10.1

επέκταση μεταβλητής (variable expansion)

Ενότητα 3.4.5

verbose

Ενότητα 2.3.2

vi(m)

Ενότητα 2.1.1

W

wait

Ενότητα 12.2.2

whereis

Ενότητα 2.1.1

which

Ενότητα 2.1.1

while

Ενότητα 9.2

μπαλαντέρ (wildcards)

Ενότητα 4.2.2.3

λέξεις άγκυρες (word anchors)

Ενότητα 4.2.2.1

χωρισμός λέξεων (word splitting)

Ενότητα 3.4.9

X

xtrace

Ενότητα 2.3.1, Ενότητα 2.3.2

Y

Z