505 γραμμές
43 KiB
Markdown
505 γραμμές
43 KiB
Markdown
+++
|
||
title = 'Προγραμματισμός με gawk μέρος 2ο'
|
||
date = '2000-04-01T00:00:00Z'
|
||
description = ''
|
||
author = 'DJ Art(mailto:djart@hellug.gr)'
|
||
issue = ['Magaz 24']
|
||
issue_weight = 3
|
||
+++
|
||
|
||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
*Το άρθρο αυτό αποτελεί το δεύτερο (και τελευταίο) μέρος της παρουσίασης της γλώσσας awk με στόχο την βοήθεια για την εκμάθησή της.*
|
||
|
||
----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
**1. Ενσωματωμένες συναρτήσεις**
|
||
-------------------------------------------------------
|
||
|
||
**2. Αριθμητικοί τελεστές**
|
||
--------------------------------------------------
|
||
|
||
**3. Εντολές ελέγχου ροής**
|
||
--------------------------------------------------
|
||
|
||
- [3.1 If](#ss3.1)
|
||
- [3.2 Υποθετικός τελεστής](#ss3.2)
|
||
- [3.3 βρόγχοι](#ss3.3)
|
||
|
||
**4. Advanced Input**
|
||
--------------------------------------------
|
||
|
||
- [4.1 Next](#ss4.1)
|
||
- [4.2 Exit](#ss4.2)
|
||
- [4.3 Getline](#ss4.3)
|
||
- [4.4 Input από αρχείο](#ss4.4)
|
||
- [4.5 Input από εντολή](#ss4.5)
|
||
- [4.6 Τερματίζοντας το Input από αρχείο ή εντολή](#ss4.6)
|
||
|
||
**5. Advanced Output**
|
||
---------------------------------------------
|
||
|
||
- [5.1 Printf](#ss5.1)
|
||
- [5.2 Output σε αρχείο](#ss5.2)
|
||
- [5.3 Output σε εντολή](#ss5.3)
|
||
- [5.4 Τερματίζοντας το Output από αρχείο ή εντολή](#ss5.4)
|
||
|
||
**6. Συναρτήσεις**
|
||
-----------------------------------------
|
||
|
||
- [6.1 Δήλωση της συνάρτησης](#ss6.1)
|
||
- [6.2 Συνάρτηση με παραμέτρους](#ss6.2)
|
||
- [6.3 Η δήλωση return](#ss6.3)
|
||
- [6.4 Η συνάρτηση system](#ss6.4)
|
||
|
||
**7. Βιβλιογραφία**
|
||
------------------------------------------
|
||
|
||
|
||
### [1. Ενσωματωμένες συναρτήσεις]{#s1}
|
||
|
||
Παρακάτω, μπορείτε να δείτε έναν πίνακα με χρήσιμες συναρτήσεις που μπορείτε να χρησιμοποιήσετε σε ένα πρόγραμμά σας:
|
||
|
||
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
|
||
\ Επιστρέφει το ημίτονο του x
|
||
sin(x)
|
||
|
||
cos(x) Επιστρέφει το συνημίτονο του x
|
||
|
||
int(x) Επιστρέφει το ακέραιο μέρος του x
|
||
|
||
log(x) Επιστρέφει το φυσικό λογάριθμο του x
|
||
|
||
exp(x) Eπιστρέφει το e υψωμένο στη δύναμη του x
|
||
|
||
sqrt(x) Επιστρέφει την τετραγωνική ρίζα του x
|
||
|
||
getline() Διαβάζει την επόμενη γραμμή από το αρχείο.\
|
||
Επιστρέφει 0 για το τέλος του αρχείου, διαφορετικά,\
|
||
επιστρέφει 1
|
||
|
||
rand() Επιστρέφει έναν τυχαίο αριθμό ανάμεσα στο 0 και στο 1.
|
||
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
|
||
|
||
|
||
### [2. Αριθμητικοί τελεστές]{#s2}
|
||
|
||
Εδώ, επίσης θα δείτε έναν πίνακα, ο οποίος παρουσιάζει τους τελεστές που μπορείτε να χρησιμοποιήσετε για να κάνετε αριθμητικές πράξεις:
|
||
|
||
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
|
||
\ Υψώνει το x στη δύναμη του y
|
||
x\^y
|
||
|
||
x\*\*y Κάνε ακριβώς την ίδια δουλειά με τον παραπάνω τελεστή
|
||
|
||
x%y Υπολογίζει το υπόλοιπο της διαίρεσης x/y
|
||
|
||
x+y Προσθέτει το x στο y
|
||
|
||
x-y Αφαιρεί το y από το x
|
||
|
||
x\*y Πολλαπλασιάζει το x με το y
|
||
|
||
x/y Διαιρεί το x με το y
|
||
|
||
-x Επιστρέφει τον αντίθετο του x (αλλάζει το πρόσημο)
|
||
|
||
++x Αυξάνει τον x κατά 1 και χρησιμοποιεί την τιμή (όλου αυτού)
|
||
|
||
x++ Χρησιμοποιεί πρώτα την τιμή του x και μετά την αυξάνει κατά 1
|
||
|
||
\--x (αντίστοιχα με τα παραπάνω)
|
||
|
||
x\-- (αντίστοιχα με τα παραπάνω
|
||
|
||
x=y Αποδίδει την τιμή του y στον x
|
||
|
||
x+=y Ισοδυναμεί με την παράσταση x=x+y
|
||
|
||
x/=y Iσοδυναμεί με την παράσταση x=x/y
|
||
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
|
||
|
||
**Παραδείγματα**\
|
||
Ακόμα μπερδευόσαστε με τα x++ και ++x ; :-) Πάμε, λοιπόν, να δούμε μέσα από παραδείγματα τί ακριβώς προσφέρουν:
|
||
|
||
x++\
|
||
Αυτή εδώ η παράσταση ισοδυναμεί με την παράσταση x=x+1. Λοιπόν, προσέξτε: όσοι ασχολούνται για πρώτη φορά με τον προγραμματισμό, πρέπει να δώσουν ιδιαίτερη
|
||
προσοχή με το σύμβολο της ισότητας. Εδώ το = δεν σημαίνει ακριβώς \"ίσον\" !!! Το σύμβολο = χρησιμοποιείται για να αποδώσει τιμές. Δηλαδή, στην ισότητα x=x+1,
|
||
δεν πρέπει κανείς να πάει και \"να φέρει το x στο πρώτο μέλος, οπότε να μείνει 0=1\" !!! Απλά, το = κάνει το εξής: αποδίδει στην μεταβλητή x την τιμή που
|
||
υπάρχει στο δεξί μέρος του, δηλαδή, αν αρχικά είχαμε ορίσει ότι το x είναι ίσο με 3, τώρα, μετά από αυτήν την δήλωση, το x θα είναι ίσο με 4.
|
||
|
||
y = x++\
|
||
Αυτή εδώ η παράσταση, αντιστοιχεί σε δύο παραστάσεις, στην y=x και στην x=x+1. Δηλαδή, αν αρχικά το x είναι ίσο με 3, τότε το y ισούται με 3 (**ΠΡΟΣΟΧΗ εδώ**),
|
||
ενώ το x πιά ισούται με 4 !!!! Κοιτάξτε και το παρακάτω παράδειγμα για να καταλάβετε:
|
||
|
||
y = \--x\
|
||
Λοιπόν, και αυτή η παράσταση αντιστοιχεί σε άλλες δύο, στην x=x-1 και στην y=x. Μα, θα μου πείτε, αυτές οι δύο δεν έχουν διαφορά με τις παραπάνω. Πρέπει να
|
||
λάβετε υπ\' όψιν την σειρά με την οποία εκτελούνται οι παραστάσεις, δηλαδή εδω, **ΠΡΩΤΑ** μειώνεται η τιμή του x κατά 1 και **ΜΕΤΑ** αποδίδεται η τιμή (του
|
||
μειωμένου πιά x) στην μεταβλητή y, δηλαδή αν είχαμε αρχικά ότι το x ισούται με 3, τότε τώρα πιά, το x **ΑΛΛΑ ΚΑΙ ΤΟ** y ισούται με 2.
|
||
|
||
|
||
### [3. Εντολές ελέγχου ροής]{#s3}
|
||
|
||
### [3.1 If]{#ss3.1}
|
||
|
||
Απο τη φύση της, η gawk έχει την εξής μορφή: αν το πρότυπο ικανοποιείται, τότε εκτελείται η πράξη. Φυσικά, έχετε τη δυνατότητα να γράψετε ένα πρόγραμμα με
|
||
\"υποθετική ροή\". Αυτό μπορείτε να το κάνετε, φυσικά, με το if.
|
||
|
||
Η γενική δομή του if έχει ως εξής:
|
||
|
||
if (υπόθεση)
|
||
εντολή που εκτελείται αν η υπόθεσή μας είναι αληθινή
|
||
else
|
||
εντολή που εκτελείται αν η υπόθεσή μας δεν είναι αληθινή
|
||
|
||
Η υπόθεσή μας μπορεί να είναι οποισδήποτε συνδυασμός προτύπων από αυτά που είπαμε στο 1ο μέρος. Τώρα, αν θέλετε να εκτελούνται περισσότερες από μία εντολές,
|
||
μετά τον έλεγχο αληθείας της υπόθεσης, τότε θα πρέπει να \"περικυκλώσετε\" τις εντολές με αγκύλες ({ }), ακριβώς όπως και στη C.
|
||
|
||
Μπορείτε να χρησιμοποιήσετε πολλά if στη σειρά (και μετά από ένα else) με τον εξής τρόπο:
|
||
|
||
if ("Linux" in magaz_subject)
|
||
print "We are studying Linux :-)"
|
||
else if ("gawk" in magaz_subject)
|
||
print "We are studying awk :-)"
|
||
else
|
||
print "We are doing nothing :-("
|
||
|
||
### [3.2 Υποθετικός τελεστής]{#ss3.2}
|
||
|
||
Η gawk σας παρέχει με αυτόν τον τελεστή, ο οποίος αποτελείται από τρείς παραμέτρους, τη δυνατότητα να εφαρμόζετε if-ελέγχους ανά πάσα στιγμή μέσα στο πρόγραμμά
|
||
σας. Η μορφή του είναι η εξής:
|
||
|
||
υπόθεση ? αποτέλεσμα σε περίπτωση αλήθειας : εναλλακτικό αποτέλεσμα (σε μη-αληθινή περίπτωση)
|
||
|
||
Αυτός ο τελεστής καθιστά τα προγράμματά σας πιο ευανάγνωστα. Ας δούμε ένα παράδειγμα χρήσης του παραπάνω τελεστή σε περίπτωση όπου ανάλογα με τον αριθμό των
|
||
αρχείων που αντιγράφηκαν, θέλουμε πληθυντικό ή ενικό:
|
||
|
||
{ print $1, "αρχεί" $1 != 1 ? "α αντιγράφηκαν" : "ο αντιγράφηκε" }
|
||
|
||
Αν θα θέλαμε να γράψουμε το παραπάνω, χρησιμοποιώντας το if, τότε θα γράφαμε:
|
||
|
||
if ( $1 != 1 )
|
||
print $1, "αρχεία αντιγράφηκαν"
|
||
else
|
||
print $1, "αρχείο αντιγράφηκε"
|
||
|
||
### [3.3 βρόγχοι]{#ss3.3}
|
||
|
||
H awk υποστηρίζει τους βρόγχους do, for και while, όπως ακριβώς αυτοί συντάσσονται στην C. Μια γενική συμβουλή (για όλους τους βρόγχους) είναι να μην ξεχνάτε να
|
||
χρησιμοποιείτε αγκύλες ({ }) όταν θέλετε μέσα στο βρόγχο να εκτελέσετε πάνω από μία εντολές. Ένα λάθος που γίνεται συχνά είναι ακριβώς αυτό, να ξεχνάει κανείς
|
||
τις αγκύλες.
|
||
|
||
#### Do
|
||
|
||
Ο βρόγχος do (συνήθως καλείται και do-while) αποτελείται από δύο μέρη: τις εντολές που θέλουμε να εκτελέσουμε και τον (υποθετικό) έλεγχο. Προσέξτε πως αυτός ο
|
||
βρόγχος έχει το χαρακτηριστικό να εκτελούνται οι εντολές που του δηλώνουμε τουλάχιστον μία φορά, καθώς ο υποθετικός έλεγχος που \"επιβάλλουμε\" αναγράφεται μετά
|
||
την δήλωση των εντολών. Για να το καταλάβετε καλύτερα, ας δούμε τη σύνταξη του do:
|
||
|
||
do
|
||
εντολές
|
||
while (υπόθεση)
|
||
|
||
π.χ:
|
||
|
||
do
|
||
print "Magaz kicks!!"
|
||
while ($1 != 1)
|
||
|
||
Το μήνυμα της print θα εκτελείται μέχρι το πρώτο πεδίο (\$1) να πάρει την τιμή 1. Όμως, ακόμα και αν το \$1 \"ξεκινάει\" με αρχική τιμή 1, τότε το μήνυμα θα
|
||
τυπωθεί. Απλά, όταν θα γίνει ο έλεγχος και \"ικανοποιηθεί\" η while, δεν θα ξαναγυρίσουμε στο do, αλλά το πρόγραμμα θα προχωρήσει στις τυχόν παρακάτω εντολές.
|
||
|
||
#### For
|
||
|
||
O βρόγχος for είναι ένας πασίγνωστος βρόγχος στις γλώσσες προγραμματισμού. Ας δούμε κατ\' ευθείαν την σύνταξή του για να καταλάβουμε τη λειτουργία του:
|
||
|
||
for (i = 0; i < 100; i++)
|
||
{
|
||
εντολή 1
|
||
εντολή 2
|
||
}
|
||
|
||
Παραπάνω, οι εντολές του βρόγχου θα εκτελεστούν 100 φορές!! Ας δούμε γιατί: Αρχικά, ορίζουμε μιά μεταβλητή, την i, η οποία θα μας χρησιμεύσει απλά και μόνο για
|
||
το πόσες φορές θα εκτελεστεί ο βρόγχος, και δίνουμε στην i την τιμή 0. Μετά, η for κοιτάει τη 2η δήλωση στην παρένθεση (οι δηλώσεις, υπενθυμίζω, χωρίζονται με
|
||
;) και κάνει τον υποθετικό έλεγχο. Στην περίπτωσή μας, ελέγχεται αν η τιμή της μεταβλητής i είναι μικρότερη από 100 και αν είναι, τότε εκτελούνται οι εντολές
|
||
που καθορίσαμε. Μετά (και εδώ φαίνεται η \"δυναμη\" της for), δεν χρειάζεται να \"κανονίσουμε\" εμείς την μεταβλητή i, αλλά έχουμε δηλώσει η i να αυξάνεται κατά
|
||
1. Η for λοιπόν, αυξάνει την τιμή της i και ξαναρχίζει: κάνει τον έλεγχο, εκτελεί της εντολές, αυξάνει την i κ.ο.κ. \... Όταν, λοιπόν, η i θα αποκτήσει την τιμή
|
||
100, τότε δεν θα εκτελεστούν οι εντολές, καθώς το αποτέλεσμα του ελέγχου 100 \< 100 είναι ψευδές (το 100 δεν είναι μικρότερο από το 100 !! :)
|
||
|
||
#### While
|
||
|
||
Ο βρόγχος while είναι αρκετά απλός και μάλλον θα έχετε ήδη καταλάβει πως λειτουργεί (από το βρόγχο do-while). Σε αντίθεση με την do, οι εντολές εκτελούνται μόνο
|
||
αν το αποτέλεσμα του υποθετικού ελέγχου, ο οποίος γίνεται στην αρχή του βρόγχου, είναι αληθής. Ας δούμε τη σύνταξή του:
|
||
|
||
while (υπόθεση)
|
||
εντολή(ες και μήν ξεχάσετε τις αγκύλες :)
|
||
|
||
Γενικά, για τους βρόγχους, να έχετε υπ\' όψιν πως μέσα στις εντολές του βρόγχου, η μεταβλητή πάνω στην οποία γίνεται ο υποθετικός έλεγχος, πρέπει να αλλάζει,
|
||
αλλιώς ο βρόγχος μας δεν τελειώνει ποτέ !!! (ατέρμων βρόγχος)
|
||
|
||
#### Έλεγχος στους βρόγχους
|
||
|
||
Όπως και στις υπόλοιπες γλώσσες προγραμματισμού, έτσι και στην awk, έχετε τη δυνατότητα να \"βγείτε\" από έναν βρόγχο (loop), \"νωρίτερα από το κανονικό\",
|
||
δηλαδή χωρίς να \"ικανοποιηθεί\" κάποιος υποθετικός έλεγχος και τερματίσει ο βρόγχος. Αυτό μπορείτε να το κάνετε με δύο εντολές: την break και την continue.
|
||
|
||
Με την εντολή break **\*ΑΚΑΡΙΑΙΑ\*** τερματίζετε τον βρόγχο και, φυσικά, όσες εντολές ακολουθούν την break **\*ΜΕΣΑ\*** στον βρόγχο, δεν εκτελούνται, αλλά το
|
||
πρόγραμμα θα συνεχίσει, εκτελώντας τις εντολές που τυχόν βρίσκονται μετά τον βρόγχο. Η εντολή break είναι σαν να εκτελείτε εκείνη την στιγμή τον υποθετικό
|
||
έλεγχο του βρόγχου, αλλά το αποτέλεσμα **\*ΒΕΒΙΑΣΜΕΝΑ\*** (από την break) είναι μή αληθές (FALSE).
|
||
|
||
Αντίθετα, η εντολή continue αναγκάζει τον βρόγχο να εκτελέσει τον υποθετικό του έλεγχο. Όσες τυχόν εντολές βρίσκονται μετά την continue (μέσα στο βρόγχο) δεν
|
||
εκτελούνται. Η continue δεν είναι σίγουρο πως θα \"τερματίσει\" το βρόγχο, αν το αποτέλεσμα του βρόγχου είναι αληθές (TRUE), τότε ο βρόγχος θα συνεχίσει να
|
||
εκτελείται. Η continue είναι ιδιαίτερα χρήσιμη αν θέλετε (για κάποιο λόγο, για κάποια συνθήκη) να \"παρακάμψετε\" κάποιες εντολές του κώδικα.
|
||
|
||
|
||
### [4. Advanced Input]{#s4}
|
||
|
||
Εξ ορισμού, η awk αυτόματα διαβάζει και εκτελεί συνέχεια την ίδια δουλειά: Διαβάζει μιά εγγραφή και αν ταιριάξει κάποιο πεδίο ή εγγραφή με το πρότυπο, τότε
|
||
εκτελεί την πράξη. Όμως, η awk σας δίνει την δυνατότητα να \"επέμβετε\" σε όλην αυτήν την διαδικασία και να πάρετε την είσοδο (input) από ένα άλλο αρχείο ή να
|
||
προκαλέσετε πρώιμο ξαναξεκίνημα της όλης διαδικασίας, να πάρετε είσοδο από την έξοδο κάποιας εντολής κλπ.
|
||
|
||
### [4.1 Next]{#ss4.1}
|
||
|
||
Η εντολή next \"υποχρεώνει\" την awk να διαβάσει την αμέσως επόμενη εγγραφή και να κάνει τα γνωστά (ταίριασμα των προτύπων και αν είναι αληθές, τότε εκτέλεση
|
||
της πράξης κλπ.), δηλαδή αγνοείται πλήρως η παρούσα εγγραφή που επεξεργάζεται η awk.
|
||
|
||
### [4.2 Exit]{#ss4.2}
|
||
|
||
Η εντολή exit, χρησιμοποιούμενη σε πράξη, συμπεριφέρεται σαν να έφτασε το τέλος του αρχείου (που επεξεργάζεται η awk). Αυτό έχει σαν συνέπεια να σταματήσει,
|
||
γενικότερα, η εκτέλεση του κώδικα, δεν εκτελούνται άλλες πράξεις, δεν ταιριάζονται άλλα πρότυπα. Στη συνέχεια, κανονικά, εκτελείται (αν υπάρχει, βέβαια) το
|
||
ειδικό πρότυπο END.
|
||
|
||
Αν τώρα, χρησιμοποιήσουμε την εντολή exit μέσα στο ειδικό πρότυπο END, τότε τερματίζεται ολόκληρο το πρόγραμμα, δεν εκτελείται τίποτα άλλο στη συνέχεια.
|
||
|
||
### [4.3 Getline]{#ss4.3}
|
||
|
||
Η εντολή getline διαβάζει μία εγγραφή \"κατηγορηματικά\", επιστρέφει 1 αν η ανάγνωση της εγγραφής ήταν επιτυχής (θυμίζω πως εξ ορισμού η κάθε γραμμή ενός
|
||
αρχείου αποτελεί μία εγγραφή), ή 0 αν δεν ήταν επιτυχής (δηλαδή αν έφτασε στο τέλος του αρχείου). Η getline συμπεριφέρεται \"κανονικά\", δηλαδή ορίζει με τον
|
||
σωστό τρόπο το \$0, ορίζει τις μεταβλητές πεδίων και τις μεταβλητές FNR, NR και NF).
|
||
|
||
### [4.4 Input από αρχείο]{#ss4.4}
|
||
|
||
Έτσι, λοιπόν, η getline μπορεί να χρησιμεύσει για να πάρετε είσοδο δεδομένων από κάποιο αρχείο, το οποίο δεν αναφέρατε στην γραμμή εντολών. Η γενική μορφή, με
|
||
την οποία χρησιμοποιούμε την getline σ\' αυτήν την περίπτωση είναι η getline \< \"filename\". Σε αυτήν την περίπτωση, αν το αρχείο υπάρχει και η getline διάβασε
|
||
εγγραφή, επιστρέφει 1, αλλιώς αν έφτασε στο τέλος του αρχείου επιστρέφει 0, ενώ αν το αρχείο δεν υπάρχει επιστρέφει -1.
|
||
|
||
ΣΗΜΕΙΩΣΗ: Και πάλι, οι μεταβλητές \$0, οι μεταβλητές πεδίων και η NF ορίζονται κανονικά, ενώ οι μεταβλητές FNR και NR **ΔΕΝ ΑΛΛΑΖΟΥΝ, ΠΑΡΑΜΕΝΟΥΝ ΩΣ ΕΙΧΑΝ !!**
|
||
|
||
### [4.5 Input από εντολή]{#ss4.5}
|
||
|
||
Μιά άλλη περίπτωση όπου χρησιμοποιείται η getline, είναι η είσοδος από UNIX εντολή. Ας δούμε πως μπορούμε να συντάξουμε κάτι τέτοιο:
|
||
|
||
while ("UNIX εντολή" | getline)
|
||
{
|
||
# ακολουθούν οι εντολές που θέλω να εκτελέσω
|
||
}
|
||
|
||
Φανταστείτε π.χ. πως θα θέλατε κάθε φορά που μπαίνει ένας χρήστης στο σύστημα, να τυπώνετε ένα μήνυμα (ή, τέλος πάντων, να κάνατε κάτι άλλο), τότε στη θέση της
|
||
UNIX εντολής θα βάζατε το who ή και το who -u.
|
||
|
||
### [4.6 Τερματίζοντας το Input από αρχείο ή εντολή]{#ss4.6}
|
||
|
||
Καλό θα είναι, κάθε φορά που χρησιμοποιείτε την getline για να \"ανοίξετε\" ένα αρχείο ή μία εντολή, δηλαδή να πάρετε είσοδο από αυτά, να τα \"κλείνετε\" όταν
|
||
τελειώσετε με αυτά. Υπάρχει ένας μέγιστος αριθμός \"ανοιχτών\" αρχείων/εντολών που επιτρέπεται σε έναν χρήστη (αυτός ο αριθμός ποικίλει από σύστημα σε σύστημα,
|
||
αλλά και ανάλογα με τις ρυθμίσεις του διαχειριστή του συστήματος). Με το να \"κλείνετε\" τις εντολές/αρχεία που χρησιμοποιήσατε, ουσιαστικά μειώνετε την
|
||
πιθανότητα να φτάσετε τον μέγιστο αριθμό. Λοιπόν, αυτό μπορείτε να το κάνετε με την εξής εντολή:
|
||
|
||
close ("filename")
|
||
|
||
Στη θέση του filename μπορείτε να χρησιμοποιήσετε είτε το όνομα κάποιας μεταβλητής (η οποία περιέχει αρχείο/εντολή) είτε το όνομα της εντολής που
|
||
χρησιμοποιήσατε (εδώ, προσέξτε να δηλώσετε την ακριβή εντολή που χρησιμοποιήσατε, π.χ. αν χρησιμοποιήσετε την who -u να γράψετε close (\"who -u\") \...).
|
||
|
||
|
||
### [5. Advanced Output]{#s5}
|
||
|
||
Μερικές πιο ειδικευμένες δυνατότητες υπάρχουν στην awk για την έξοδο (output). Αυτές είναι: το \"όμορφο\" φορμάρισμα του κειμένου, η ανακατεύθυνση του output σε
|
||
αρχεία (κειμένου) και η διασωλήνωση του output στην είσοδο (input) άλλων (εξωτερικών) εντολών του command prompt.
|
||
|
||
### [5.1 Printf]{#ss5.1}
|
||
|
||
Η εντολή print που είδαμε (στο 1ο μέρος), είναι αρκετά απλή και το output της είναι και αυτό αρκετά απλό. Αν, όμως, θέλετε να έχετε μορφοποιημένη την έξοδο του
|
||
προγράμματός σας (παραγωγή στηλών, για παράδειγμα), τότε θα πρέπει να χρησιμοποιήσετε την δανεισμένη από τη C εντολή, την printf. H printf έχει την εξής γενική
|
||
μορφή:
|
||
|
||
printf("αλφαριθμητικό ελέγχου", λίστα_ορισμάτων, 1ο όρισμα, 2ο όρισμα, κ.ο.κ.)
|
||
|
||
Το αλφαριθμητικό ελέγχου, μπορεί να αποτελείται από τα εξής στοιχεία:
|
||
|
||
1. Απλούς χαρακτήρες (δηλαδή κείμενο)
|
||
2. ειδικούς μεταχαρακτήρες (θυμάστε το \\n π.χ.)
|
||
3. Τις διαταγές φόρμας
|
||
|
||
Ας δούμε από ένα παράδειγμα για τα παραπάνω τρία στοιχεία, και μετά να μιλήσουμε περισσότερο για τις διαταγές φόρμας:
|
||
|
||
1. printf(\"hello world\")
|
||
2. printf(\"\\f\")
|
||
3. printf(\"%22s\", \"Magaz\")
|
||
4. Και φυσικά, συνδυασμό όλων αυτών των στοιχείων (θα το δούμε)
|
||
|
||
#### Διαταγές φόρμας
|
||
|
||
Λοιπόν, κάθε διαταγή φόρμας αποτελείται από 3 μέρη. Στο 1ο μέρος, **ΠΑΝΤΑ**, γράφουμε το σύμβολο του ποσοστού (**%**). Κάθε διαταγή φόρμας αρχίζει με αυτό το
|
||
σύμβολο. Το 2ο μέρος συμπληρώνεται προαιρετικά. Συμπληρώνεται με αριθμούς, οι οποίοι υποδηλώνουν το μέγιστο μήκος της εξόδου. Τέλος, το 3ο μέρος αποτελείται από
|
||
ειδικούς χαρακτήρες, οι οποίοι υποδηλώνουν το είδος της εξόδου (αν είναι αλφαριθμητικό, αν είναι δεκαδικός αριθμός κλπ.) Θα μιλήσουμε τώρα αναλυτικότερα για το
|
||
2ο μέρος και μετά θα δούμε έναν πίνακα με τους χαρακτήρες του 3ου μέρους.
|
||
|
||
Ο αριθμός, το εύρος πεδίου, αποτελείται από δύο αριθμούς οι οποίοι χωρίζονται με μία τελεία (.), δηλαδή είναι της μορφής x.y. Αν η έξοδος μας είναι δεκαδικός
|
||
αριθμός, τότε ο αριθμός αριστερά από την τελεία υποδηλώνει τον αριθμό ψηφίων **ΟΛΟΥ** του αριθμού (*συμπεριλαμβανόμενης της τελείας (.) του αριθμού*), ενώ ο
|
||
αριθμός δεξιά από την τελεία υποδηλώνει τον αριθμό ψηφίων του δεκαδικού μέρους του αριθμού. Αν τώρα, η έξοδος μας δεν είναι δεκαδικός αριθμός, αλλά ο,τιδήποτε
|
||
άλλο, τότε ο αριθμός αριστερά από την τελεία είναι ο ελάχιστος αριθμός ψηφίων/χαρακτήρων αυτού που θα τυπώσουμε, ενώ ο αριθμός δεξιά της τελείας είναι ο
|
||
μέγιστος αριθμός ψηφίων/χαρακτήρων και ο \"πραγματικός\" αριθμός των ψηφίων/χαρακτήρων που τελικά θα εκτυπωθούν. Δηλαδή, μπορείτε κάλλιστα να παραλείψετε τον
|
||
αριθμό αριστερά της τελείας (π.χ. %.4s)
|
||
|
||
**ΣΗΜΕΙΩΣΕΙΣ:**\
|
||
Αν θέλετε μέσα από την printf να τυπώσετε τον χαρακτήρα %, τότε θα γράψετε μέσα στον κώδικά σας %%.\
|
||
Εξ ορισμού, η έξοδος της printf είναι σε δεξιά στοίχιση. Αν θέλετε να έχετε αριστερή, τότε μπροστά από τον αριθμό που βρίσκεται αριστερά της τελείας (στο εύρος
|
||
πεδίου) βάζετε το σύμβολο μείον (-).
|
||
|
||
Παρακάτω, βλέπετε τον πίνακα με τους χαρακτήρες που μπορείτε να χρησιμοποιήσετε. Στη συνέχεια θα δούμε και παραδείγματα.
|
||
|
||
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
|
||
\ **Σημασία**
|
||
**Κωδικός φόρμας**
|
||
|
||
%c Χαρακτήρας ASCII
|
||
|
||
%d Ακέραιος δεκαδικός αριθμός
|
||
|
||
%i Το ίδιο με το %d
|
||
|
||
%e Εκτύπωση δεκαδικού αριθμού κινητής υποδιαστολής με επιστημονική\
|
||
σημειογραφία, δηλαδή της μορφής \[-\]x.xxxxe\[-/+\]xxx
|
||
|
||
%f Δεκαδικός κινητής υποδιαστολής
|
||
|
||
%g Η awk κρίνει και διαλέγει για έναν αριθμό μία από τις μορφές %e και\
|
||
%f (όποια έχει μικρότερο μήκος) και, παράλληλα, \"απαλοίφει\" άχρηστα μηδενικά
|
||
|
||
%o Μη προσημασμένος (χωρίς πρόσημο) ακέραιος οκταδικός αριθμός
|
||
|
||
%s Αλφαριθμητικό
|
||
|
||
%x Μη προσημασμένος ακέραιος δεκαεξαδικός αριθμός (με πεζά τα abcdef)
|
||
|
||
%X Μη προσημασμένος ακέραιος δεκαεξαδικός αριθμός (με κεφαλαία τα ABCDEF)
|
||
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
|
||
|
||
#### Παραδείγματα
|
||
|
||
Επειδή θέλω να σας δείξω την λειτουργία του εύρους πεδίου, θα συμβολίζω τα κενά με παύλα (-), ώστε να μπορείτε να μετρήσετε τους χαρακτήρες και τα κενά (και να
|
||
βγάλετε τα συμπεράσματά σας):
|
||
|
||
printf("%10d\n", 29) (θα έχει σαν αποτέλεσμα:) --------29
|
||
|
||
printf("%-10d\n", 29) 29--------
|
||
|
||
printf("%10.3f\n", 123.56) ---123.560
|
||
|
||
printf("%15s\n", "Linux Magaz") ----Linux Magaz
|
||
|
||
printf("%-15s\n", "Linux Magaz") Linux Magaz----
|
||
|
||
### [5.2 Output σε αρχείο]{#ss5.2}
|
||
|
||
Όπως και στην περίπτωση της getline, έτσι και εδώ, μπορείτε να χρησιμοποιήσετε τα σύμβολα της ανακατεύθυνσης για να στείλετε την έξοδο κατ\' ευθείαν μέσα σε ένα
|
||
αρχείο. Π.χ:
|
||
|
||
printf("hello world\n") > "filename"
|
||
printf("hello world\n") >> "filename"
|
||
|
||
### [5.3 Output σε εντολή]{#ss5.3}
|
||
|
||
Σε αυτήν την περίπτωση, έχετε την δυνατότητα να στείλετε έξοδο (output) στην είσοδο (input) μιάς εξωτερικής εντολής του UNIX. Π.χ:
|
||
|
||
printf("hello world\n") | "sort -t , "
|
||
|
||
### [5.4 Τερματίζοντας το Output από αρχείο ή εντολή]{#ss5.4}
|
||
|
||
Ακριβώς για τους ίδιους λόγους που αναφέραμε στην getline, έτσι και εδώ, καλό θα ήταν να \"κλείνετε\" ένα αρχείο ή μία εντολή αφού τελειώσετε με αυτά. Η σύνταξη
|
||
είναι ακριβώς η ίδια: close (\"filename\") και στη θέση του filename χρησιμοποιείτε είτε όνομα αρχείου, είτε το όνομα της **ΑΚΡΙΒΟΥΣ** εντολής που τρέξατε με
|
||
διασωλήνωση, είτε το όνομα κάποιας μεταβλητής που \"δείχνει\" σε αρχείο.
|
||
|
||
|
||
### [6. Συναρτήσεις]{#s6}
|
||
|
||
**ΠΡΟΣΟΧΗ!!!**\
|
||
Οι συναρτήσεις (που ορίζονται από τον χρήστη) δεν υπάρχουν στην \"αυθεντική\" awk, αλλά προστέθηκαν αργότερα στην nawk και υποστηρίζονται από την gawk.
|
||
|
||
Όπως θα καταλάβατε, εκτός από τις ενσωματωμένες συναρτήσεις η gawk σας επιτρέπει να φτιάξετε τις δικές σας. Μία συνάρτηση χρησιμεύει σε ένα πρόγραμμα αν θέλετε
|
||
να επαναλάβετε τα ίδια κομμάτια κώδικα σε πολλά σημεία του προγράμματος, ώστε να μην ξαναγράφετε κάθε φορά το ίδιο πράγμα. Η χρήση των συναρτήσεων απαιτεί δύο
|
||
βήματα: την δήλωση της συνάρτησης και την κλήση της συνάρτησης μέσα στο πρόγραμμα.
|
||
|
||
### [6.1 Δήλωση της συνάρτησης]{#ss6.1}
|
||
|
||
Παρακάτω, θα δούμε τον κώδικα που απαιτείται για να δηλώσετε μιά συνάρτηση. Επιπλέον, να σημειώσω πως δεν παίζει κανέναν ρόλο η θέση που θα δηλώσετε την
|
||
συνάρτηση. Μπορείτε κάλλιστα να την δηλώσετε στο τέλος του προγράμματος.
|
||
|
||
function όνομα_συνάρτησης(παράμετροι) {
|
||
κώδικας της συνάρτησης
|
||
}
|
||
|
||
Τώρα θα δούμε τη λειτουργία των συναρτήσεων μέσα από τρία παραδείγματα. Το πρώτο παράδειγμα θα δείχνει την συνάρτηση στην απλή της μορφή (χωρίς παραμέτρους), το
|
||
δεύτερο παράδειγμα θα δείχνει τη χρήση, λειτουργία και χρησιμότητα των παραμέτρων, ενώ στο 3ο παράδειγμα, θα μιλήσουμε για την δήλωση return και θα δούμε το
|
||
αντίστοιχο παράδειγμα.
|
||
|
||
BEGIN { function1() }
|
||
|
||
function function1() {
|
||
printf("Magaz τεύχος 24\n");
|
||
printf("Άρθρο για gawk\n");
|
||
}
|
||
|
||
Όταν τρέξουμε το πρόγραμμα, το αποτέλεσμα θα είναι να μας τυπώσει στην οθόνη το περιεχόμενο των δύο printf, όπως ορίζονται μέσα στην συνάρτηση. Δώστε ιδιαίτερη
|
||
έμφαση στις παρενθέσεις της συνάρτησης, πάντα πρέπει να τις γράφετε (σε αντίθεση με τις ενσωματωμένες συναρτήσεις της awk, όπου είναι προαιρετική η αναγραφή των
|
||
παρενθέσεων).
|
||
|
||
### [6.2 Συνάρτηση με παραμέτρους]{#ss6.2}
|
||
|
||
Όταν χρησιμοποιούμε παραμέτρους στη συνάρτηση, τότε η αριθμητική αξία της μεταβλητής που αποτελεί την παράμετρο, αντιγράφεται και μετά \"περνάει\" στην
|
||
συνάρτηση. Αυτό έχει σαν αποτέλεσμα η αρχική τιμή της μεταβλητής-παραμέτρου να παραμένει αναλλοίωτη. Αυτό είναι ένα πλεονέκτημα, μπορεί να μας φανεί σε πολλές
|
||
περιπτώσεις χρήσιμο. Βέβαια, υπάρχει πάντα και η δυνατότητα να αλλοιωθεί, θα το δούμε παρακάτω. Ας δούμε τώρα ένα παράδειγμα:
|
||
|
||
BEGIN { variable = 0; function1(variable);
|
||
printf("Η τιμή της μεταβλητής variable είναι: %d\n", variable); }
|
||
|
||
function function1(variable2) {
|
||
variable2++;
|
||
printf("Η τιμή της μεταβλητής variable2 είναι: %d\n", variable2); }
|
||
|
||
Όταν εκτελέσουμε το πρόγραμμα θα δούμε πως θα μας τυπωθούν στην οθόνη δύο γραμμές. Η πρώτη γραμμή (που θα προέρχεται από την συνάρτηση) θα λέει πως η variable2
|
||
είναι ίση με 1, ενώ η δεύτερη θα λέει πως η variable είναι ίση με 0. Βλέπετε, λοιπόν, πως η τιμή της variable αντιγράφεται στην variable2 και δεν αλλάζει.
|
||
|
||
### [6.3 Η δήλωση return]{#ss6.3}
|
||
|
||
H return έχει δύο λειτουργίες: είτε να επιστρέψετε την τιμή της παραμέτρου, είτε να βγείτε από την συνάρτηση νωρίτερα. Η σύνταξή της είναι: return
|
||
όνομα\_μεταβλητής. Μπορείτε σε κάθε συνάρτηση να επιστρέψετε την τιμή *μόνο μίας μεταβλητής*, **όχι παραπάνω**. Ας δούμε το παράδειγμα:
|
||
|
||
BEGIN { variable = 0; function1(variable);
|
||
printf("Η τιμή της μεταβλητής variable είναι: %d\n", variable); }
|
||
|
||
function function1(variable2) {
|
||
variable2++;
|
||
printf("Η τιμή της μεταβλητής variable2 είναι: %d\n", variable2);
|
||
return variable2; }
|
||
|
||
Σε αυτήν την περίπτωση, θα τυπωθούν δύο γραμμές πάλι. Και στις δύο γραμμές η τιμή των μεταβλητών θα είναι ίση με 1, καθώς η τιμή της variable2 επέστρεψε στην
|
||
τιμή της variable.
|
||
|
||
### [6.4 Η συνάρτηση system]{#ss6.4}
|
||
|
||
Η συνάρτηση system είναι ενσωματωμένη στην awk. Είναι διαφορετική από τις άλλες, δεν ανήκει ούτε στην κατηγορία των αριθμητικών ούτε στην κατηγορία των
|
||
αλφαριθμητικών συναρτήσεων. Αυτό που πραγματικά κάνει είναι να εκτελεί το αλφαριθμητικό που της δόθηκε ως παράμετρος, επιτρέποντας στον προγραμματιστή να
|
||
εκτελεί απ\'ευθείας εντολές μέσα από το πρόγραμμα. Η σύνταξη της system έχει ως εξής:
|
||
|
||
system ("εντολή")
|
||
|
||
|
||
### [7. Βιβλιογραφία]{#s7}
|
||
|
||
Για την επίτευξη αυτού του άρθρου (συμπεριλαμβανομένου, φυσικά, και του 1ου μέρους) συμβουλεύτηκα τις εξής πηγές:
|
||
|
||
- Την man page της εντολής gawk (man gawk)
|
||
- Το βιβλίο \"Linux Unleashed\" της SAMS
|
||
- Το βιβλίο \"UNIX: Θεωρία και πράξη\" του Κώστα Ν. Γιαλελή
|
||
|
||
Αν θα θέλατε να κάνετε ένα βήμα παραπάνω από το άρθρο, θα σας συμβούλευα πριν ψάξετε οπουδήποτε αλλού, να διαβάσετε τουλάχιστον μία φορά το man page της gawk.
|
||
Είναι πολύ κατατοπιστικό και πολύ περιεκτικό.
|
||
|