[eeei.gr Logo]
Επικοινωνία
Ταυτότητα
Μαθήματα Internet | Μαθήματα Προγραμματισμού | Net Business | Τα νέα του Internet | Ο Κόσμος του Αύριο

Αποθήκευση των αποτελεσμάτων ενός προγράμματος σε ένα αρχείο (print redirection)

Μέχρι τώρα, κάθε φορά που δημιουργούσαμε ένα πρόγραμμα τα αποτελέσματα των εργασιών του εμφανίζονταν στην οθόνη μέσω της εντολής print. Η Perl διαθέτει ένα default filehandle με το όνομα STDOUT (standard output). Όταν λοιπόν λέμε στην Perl να τυπώσει, εννοούμε να τυπώσει σε αυτό που γνωρίζει (δηλαδή στην οθόνη η οποία αποτελεί το STDOUT).

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

#!/usr/bin/perl -w

use strict;

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

my $file = '/mnt/win_e/Ex0204.log';

Δηλώνω το αρχείο που θέλω να διαχειριστώ. Στην προκειμένη περίπτωση πρόκειται για το log file ενός web server. Το αρχείο αυτό είναι σε text μορφή (ASCII) και η Perl μπορεί να το ανοίξει και να το διαχειριστεί χωρίς πρόβλημα. Το αρχείο αυτό αποτελείται από γραμμές με περιεχόμενο όπως το ακόλουθο:

2002-04-01 00:00:58 151.204.127.149 - 62.1.204.6 80 GET /news/newszoom.asp?id=4689 200 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.1;+Q312461) ClientId=1082294 http://www.aw.gr/news/Paper.asp?in_PaperID=84

ή

2002-04-01 00:00:58 151.204.127.149 - 62.1.204.6 80 GET /news/default.htm - 200 Mozilla/4.0+(compatible;+MSIE+6.0;+Windows+NT+5.1;+Q312461) ClientId=1082294 http://www.aw.gr/news.asp

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

my $statfile = 'data.txt';

Δηλώνω το αρχείο στο οποίο θέλω να αποθηκευτούν τα αποτελέσματα της εργασίας του προγράμματος.

my @page_stats;

Το αρχείο Ex0204.log το άνοιξα προηγουμένως με έναν editor και παρατήρησα ότι αποτελείται από πολλές γραμμές κειμένου, κάθε μια από τις οποίες αντιστοιχεί σε μια κλήση προς τον web server. Αποφάσισα λοιπόν ότι αυτό που θα κάνω είναι να δημιουργήσω μια array όπου κάθε στοιχείο της θα είναι και μια γραμμή από το αρχείο Ex0204.log. Αντί όμως για όλο το περιεχόμενο του αρχείου η @page_stats θα περιέχει μόνο τα στοιχεία που με ενδιαφέρουν, δηλαδή κλήσεις σε συγκεκριμένες web σελίδες.

open (LOGFILE, "$file") || die "can't open file: $!";

Ανοίγω το Ex0204.log χρησιμοποιώντας ένα file handle που το ονόμασα LOGFILE.

while (<LOGFILE>) {

if ($_ =~ /id=/)

{

push (@page_stats, $_);

}

}

Όλα τα παραπάνω τα έχετε συναντήσει ήδη σε προηγούμενα μαθήματα. Λέω στην Perl ότι όσο διαχειρίζεται το LOGFILE (που με τη «μαγική» While το κοιτάει γραμμή γραμμή), αν η τρέχουσα γραμμή (δηλαδή η γραμμή που κοιτάει εκείνη τη στιγμή, δηλαδή η $_) περιέχει την ακολουθία χαρακτήρων (string) id= τότε αυτή η γραμμή να πηγαίνει ολόκληρη και να αποθηκεύεται ως μια ξεχωριστή τιμή της array @page_stats.

(Αναζητούμε την ακολουθία id= επειδή γνωρίζουμε ότι μόνο όσες γραμμές περιέχουν αυτούς τους χαρακτήρες αναφέρονται σε δυναμικές σελίδες.)

close (LOGFILE);

Αφού δεν μας χρειάζεται πλέον το file handle LOGFILE το κλείνουμε.

open (WRITEFILE, "+>$statfile") or die "can't open file: $!";

Ανοίγουμε το αρχείο στο οποίο θα τοποθετήσουμε τα περιεχόμενα της μεταβλητής @page_stats και δίνουμε στο file handle το όνομα WRITEFILE. Προσέξτε ότι:

  1. Το όνομα του αρχείου βρίσκεται μέσα σε εισαγωγικά («») επειδή δεν δηλώνουμε το ίδιο το όνομα του αρχείου, αλλά μια μεταβλητή η οποία το περιέχει. Αν δηλώναμε απευθείας το όνομα του αρχείου, τότε αντί για εισαγωγικά θα βάζαμε αποστρόφους (‘’).
  2. Του ονόματος του αρχείου προηγούνται οι χαρακτήρες +>. Η σημασία όλων αυτών των προσδιοριστικών είναι:

<

Ανοίγουμε το αρχείο μόνο για να διαβάσουμε το περιεχόμενό του (reading). Το < αποτελεί την default τιμή. Αν δηλαδή δεν γράψουμε τίποτε εννοείται ότι το αρχείο θα ανοίξει μόνο για ανάγνωση.

>

Ανοίγουμε το αρχείο μόνο για καταγραφή (writing).

>>

Ανοίγουμε το αρχείο μόνο για προσθήκη (appending).

+<

Ανοίγουμε το αρχείο για καταγραφή ή ανάγνωση (reading or writing).

+>

Η Perl διαγράφει όλα τα περιεχόμενα του αρχείου και το ανοίγει για καταγραφή ή ανάγνωση (reading or writing).

my $old_output = select;

select WRITEFILE;

Η εντολή select καθορίζει πού θα οδηγηθούν τα αποτελέσματα της εντολής print. ’ρα εμείς θα έπρεπε να δηλώσουμε απλώς select WRITEFILE και αυτομάτως έχει γίνει redirection της εκτύπωσης στο αρχείο που θέλουμε (εδώ στο data.txt που δηλώσαμε με τη μεταβλητή $statfile).

Ως προνοητικοί άνθρωποι που είμαστε όμως, πριν το κάνουμε αυτό αποθηκεύσαμε το προηγούμενο περιεχόμενο της select στη μεταβλητή $old_output. Το γιατί θα το δείτε παρακάτω.

print "@page_stats;\n";

Τυπώνουμε το περιεχόμενο της @page_stats που σημαίνει ότι η Perl το αποθηκεύει στο αρχείο data.txt.

select $old_output;

Η εργασία μας τελείωσε, αλλά όχι απαραίτητα και το πρόγραμμα. Πιθανώς να πρέπει να γίνουν και άλλες δουλειές «παρακάτω», δηλαδή να προσθέσουμε και άλλο κώδικα τώρα ή αργότερα. Με το select μας όμως εμείς «χαλάσαμε» την εντολή print και τώρα οδηγεί τα αποτελέσματα σε διαφορετικό «σημείο» απ’ ό,τι προηγουμένως.

Εδώ το πρόγραμμα είναι δικό μας και αρκετά μικρό ώστε θυμόμαστε πολύ καλά τι συνέβαινε προηγουμένως (η print χρησιμοποιούσε το file handle STDOUT). Υπάρχει όμως η περίπτωση να χρειάστηκε να μπούμε «στη μέση» ενός μεγάλου προγράμματος που έχει φτιάξει κάποιος άλλος (ή εμείς αλλά πριν από τόσο καιρό που δεν θυμόμαστε πλέον ακριβώς τι κάναμε σε κάθε σημείο του).

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

print "edo eimaste pali\n";

Ελέγχουμε ότι πράγματι η print επέστρεψε στις παλαιές της συνήθειες (εμφάνιση του αποτελέσματος, δηλαδή του «edo eimaste pali» στην οθόνη).

Ολόκληρος ο κώδικας του παραπάνω προγράμματος είναι ο:

#!/usr/bin/perl -w

use strict;

my $file = '/mnt/win_e/Ex0204.txt'; # To log file

my $statfile = 'data.txt'; # To target file

my @page_stats; # Statistika poy exoyn na kanoyn me web selides

open (LOGFILE, "$file") || die "can't open file: $!";

while (<LOGFILE>) {

if ($_ =~ /id=/)

{

push (@page_stats, $_);

}

}

close (LOGFILE);

open (WRITEFILE, "+>$statfile") or die "can't open file: $!";

my $old_output = select;

select WRITEFILE;

print "@page_stats;\n";

select $old_output;

print "edo eimaste pali\n";


Τρέχουσα Ενότητα: Perl


 

Φιλικά - συνεργαζόμενα sites: Left Handed Products


© Eeei.gr 2009