perl script
Pavlos Parissis
p_pavlos at freemail.gr
Wed Mar 26 10:05:04 EET 2003
On Wed, 26 Mar 2003 02:20:04 +0200
Giorgos Keramidas <keramida at ceid.upatras.gr> wrote:
> On 2003-03-26 01:00, Pavlos Parissis <p_pavlos at freemail.gr> wrote:
> > Καλησπέρα,
> > Έχω φτιάξει ένα απλό perl script το οποίο προσθέτει την επιλογή
> > "logging" στα ufs filesystems μέσα σε ένα solaris /etc/vfstab.
> > Αλλά κάποιο λόγο που έχω εδώ 2 ώρες που προσπαθώ δεν τον έχω βρει δεν
> > δουλεύει.
>
> Άμα σου πήρε 2 ώρες για να γράψεις αυτό το πράγμα που δεν ελέγχει
> σχεδόν τίποτα για λάθη, συγγνώμη κιόλας, αλλά γιατί γράφεις Perl;
Ίσως λέω ίσως γιατί θέλω να μάθω perl.
> > ###########################
> > use warnings;
> > use strict;
> >
> > my $file;
> > my $lines;
> > my @fields;
> > my $temp_line;
> >
> > $file="vfstab";
> >
> > open (FOUT, ">$file.out");
> > open (FIN, "$file") or die "ATTENTION: The /etc/vfstab does not exists: $!\n";
>
> Bullshit! Αφού το αρχείο που προσπαθείς να κάνεις open() δεν είναι το
> /etc/vfstab αλλά το "vfstab" (χωρίς full path), γιατί λες αηδίες στον
> user στο μήνυμα λάθους;
όταν άρχισα να φτιάχνω το script πήρα το αρχείο το έβαλα στο σύστημα για να κάνω τις δοκιμές,
και όπως βλέπεις η $file δεν έχει το full path του αρχείο αλλά αυτό που έχω κάτω απο το τρέχων κατάλογο
που δουλεύω και κάνω τις δοκιμές.Τον έλεγχο τον έβαλα για να δώ οτι δουλεύει.
Σιγά μην έκανα τις δοκιμές πάνω στο system file έτσι απλά.
>
> Ο σωστός τρόπος είναι να κάνεις κάτι σαν:
>
> my $vfstab = "/etc/vfstab";
>
> open(VFSTAB, "$vfstab") || die "open";
>
> Ένα άλλο μελανό σημείο είναι ότι το script ανοίγει το FOUT πριν καν
> δοκιμάσει να ανοίξει το FIN. Αυτό έχει δυο πιθανά προβλήματα:
>
> α) Αφενός δεν ελέγχεις αν το open(FOUT, ...) πέτυχε ή όχι.
>
> β) Δεν κάνεις κάποιο έλεγχο παρακάτω να σιγουρευτείς ότι
> τουλάχιστον μια γραμμή γράφεται στο $file.out και μπορεί να
> καταλήξεις να κάνεις μια προσπάθεια για overwrite του $file
> με το $file.out και να σβήσεις ουσιαστικά το $file.
>
> > foreach $lines (<FIN>){
> > chop($lines);
>
> Καλύτερα είναι να χρησιμοποιείς την chomp(); Επίσης, είναι καλή ιδέα
> όταν γράφεις με 'strict' και 'warnings' ενεργοποιημένα να
> προγραμματίζεις με ασφαλή τρόπο. Στο παραπάνω, τι γίνεται όταν το
> $line == undef επειδή το <FIN> έφτασε στο end of file του;
θα κλείσει το loop,τουλάχιστον αύτο κατάλαβα έγω.
> Σου προτείνω να χρησιμοποιήσεις τουλάχιστον ένα έλεγχο defined($line)
> κάπου εκεί πέρα, για να μη σου πω να το γράψεις όπως όλος ο καλός
> κόσμος και όχι με αυτή την αηδία του foreach:
>
> my $lc = 0;
> while (defined($line = <FIN>)) {
> chomp $line;
> $lc++;
>
> @ary = split /\s+/, $line;
> die "Missing fields in line $lc of $vfstab\n"
> if ($#ary != 6);
>
> ...
>
> }
>
> > @fields = split /\s+/, $lines;
> > print "$fields[3]\n";
>
> Εδώ τυπώνεις μόνο το πεδίο [3]. Δεν τυπώνεις τα πεδία [0] - [3].
>
αύτο το έκανα για να δώ άν έχω data στο array μου.
> > if ($fields[3] eq "ufs" and $fields[6] ne "logging"){
>
> Γιατί λυπάσαι τις παρενθέσεις και δεν λυπάσαι τονν εαυτό σου που θα
> ψάχνεσαι μετά από λίγο γιατί κάνει βλακείες το πρόγραμμα; Α συγγνώμη,
> ήδη ψάχνεσαι...
>
> > if ($fields[6] eq "-"){
> > $fields[6] = "logging";
> > }
> > else {
> > $fields[6] = "$fields[6]". ",logging";
> > }
>
> Πως είσαι τόσο εξοργιστικά σίγουρος ότι ΥΠΑΡΧΕΙ πεδίο [6];
διότι το αρχείο έχει 7 πεδία
/dev/md/dsk/d2 - - swap - no -
1 2 3 4 5 6 7
> > }
> >
> > foreach $temp_line (@fields){
> > print FOUT "$temp_line ";
> > }
>
> Λάθος τρόπος να τυπώνεις πεδία. Μάθε τη join().
θα την μάθω και αύτην που θα πάει.
>
> > print FOUT "\n";
> > }
> > close(FIN);
> > close(FOUT);
> > #system("/bin/cp $file\{,.bak\}");
> > #system("/bin/rm $file");
> > #system("/bin/mv $file.out $file");
>
> Αυτά τα τελευταία ΟΥΤΕ ΠΟΥ ΝΑ ΣΟΥ ΠΕΡΑΣΕΙ ΑΠΟ ΤΟ ΜΥΑΛΟ να τα κάνεις
> uncomment. Αν θες το καλό σου, πέτα το όλο το script όπως είναι και
> κοίτα στο τέλος του mail. Κι όταν κάνεις κάτι σε πρόγραμμα που μπορεί
> να αποτύχει, *ΠΑΝΤΑ* να ελέγχεις αν πέτυχε ή όχι και γιατί.
οκ αύτο θα το κάνω αλλά είπαμε μαθαίνω
>
> > ###############################
> >
> > το αρχείο vfstab έχει αυτά:
> >
> > fd - /dev/fd fd - no -
> > /proc - /proc proc - no -
> > /dev/md/dsk/d2 - - swap - no -
> > /dev/md/dsk/d1 /dev/md/rdsk/d1 / ufs 1 no -
> > /dev/md/dsk/d3 /dev/md/rdsk/d3 /opt ufs 2 yes -
> > swap - /tmp tmpfs - yes size=512m
> >
> > και όταν το τρέχω πέρνω [...]
>
> Ορίστε η έξοδος από το filter που θα βρεις παρακάτω:
>
> giorgos at gothmog[02:15]/tmp$ perl lala.pl < vfstab
> fd - /dev/fd fd - no -
> /proc - /proc proc - no -
> /dev/md/dsk/d2 - - swap - no -
> /dev/md/dsk/d1 /dev/md/rdsk/d1 / ufs 1 no logging
> /dev/md/dsk/d3 /dev/md/rdsk/d3 /opt ufs 2 yes logging
> swap - /tmp tmpfs - yes size=512m
>
> Και φυσικά, είναι filter και δεν προσπαθεί να κάνει παπάδες σε ένα
> quick and dirty script με file open και redirects και system() κλήσεις
> στο shell για να κάνει ένα απλό rename. Jesus!...
>
Γιώργο σε ευχαριστώ για το μάθημα και τις παρατηρησείς σου, θα προσπαθήσω την επόμενη φορά
να είμαι πιο προσεχτικός. Αλλά και εσύ να είσαι λίγο πιο χαλαρός στον λόγο σού.
Διότι αν κάποιος δέν ξέρει ή δεν έχει διαβάσει πότε emails σου, διαβάσει το γράμμα και
σίγουρα θα παρεξηγηθεί με τον τρόπο που εκφράζεσαι.
Παύλος
> #!/usr/bin/perl
>
> use warnings;
> use strict;
>
> my $lc = 0; # current line number
> my $line = undef;
> my @ary = undef;
> while (defined($line = <STDIN>)) {
> chomp $line;
> $lc++;
>
> @ary = split /\s+/, $line;
> die "Missing fields in line $lc\n"
> if ($#ary != 6);
> if ($ary[3] eq "ufs") {
> if ($ary[6] eq "-") {
> $ary[6] = "logging";
> } else {
> $ary[6] .= ",logging";
> }
> $line = join(" ", @ary);
> }
> print "$line\n";
> }
>
> ----------------------------------------------------------------------------
> EOP ::= End of Perls
>
>
> --
> linux-greek-users mailing list -- http://lists.hellug.gr
More information about the Linux-greek-users
mailing list