Η Perl έχει διάφορα ήδη μεταβλητών οι οποίες χωρίζονται σε διαφορετικές κατηγορίες με βάση τη δομή των δεδομένων και όχι το είδος τους. Έτσι όλες (ή οι περισσότερες) μεταβλητές της Perl μπορούν να είναι είτε αριθμοί, είτε αλφαριθμητικοί χαρακτήρες (γράμματα και αριθμοί μαζί), είτε λογικοί τελεστές ("ΑΛΗΘΕΣ", "ΨΕΥΔΕΣ"). H διαφορά στα είδη των μεταβλητών έγκειται στην δομή των δεδομένων, αν δηλαδή πρόκειται για μονοδιάστατο δεδομένο, λίστα ή πίνακα που είναι διατεταγμένος ή όχι. Το συγκεκριμένο κεφάλαιο ξεκινά με την πιο απλή από αυτές τις δομές. Αυτή των μονοδιάστατων, απλών βαθμωτών μεταβλητών.
Oι βαθμωτές μεταβλητές, στις οποίες στο εξής θα αναφερόμαστε και ως scalar variables είναι μονοδιάστατα δεδομένα που μπορεί να είναι:
Εισαγωγή μεταβλητών
Πώς εισάγουμε μια μεταβλητή σε ένα πρόγραμμα; Στην Perl όπως και σε άλλες γλώσσες αυτή η διαδικασία εμπεριέχει δύο διακριτά στάδια. 1 Την δήλωση της μεταβλητής με το όνομα και τον τύπο της και 2. την απόδοσης σε αυτήν μιας τιμής. Στην Perl η δήλωση μεταβλητής γίνεται με το όνομά της στο οποίο προηγείται ένα πρόθεμα σύμβολο που χαρακτηρίζει τον τύπο της. Για τις βαθμωτές μεταβλητές το συμβολο είναι το "$". Σε ό,τι αφορά τα ονόματα των μεταβλητών η Perl έχει κάποιους κανόνες που μπορούν να συνοψιστούν στις εξής απαγορεύσεις:
Έτσι οι μεταβλητές $dna, $my_protein, $table_17 είναι σωστές αλλά οι $my name, $18t και $hey[you] είναι λάθος.
Η έννοια της εισαγωγής μιας μεταβλητής σε ένα πρόγραμμα ενέχει τον χαρακτήρα "απόδοσης τιμής". Στην Perl (αλλά και στις περισσότερες γλώσσες προγραμματισμού) η διαδικασία εισαγωγής μιας μεταβλητής περιλαμβάνει:
α) Τη δήλωση της μεταβλητής. Ποιο θα είναι το όνομα της μεταβλητής και τι είδους δεδομένα θα περιέχει
β) Της απόδοσης τιμής στη μεταβλητή αυτή. Ποια τιμή θα πάρει η μεταβλητή.
Στην Perl η δήλωση της μεταβλητής γίνεται απλά με την αναφορά του ονόματός της δίπλα σε ένα καθορισμένο σύμβολο που αντιστοιχεί στον τύπο της. Για τις βαθμωτές μεταβλητές αυτό το σύμβολο είναι το σύμβολο του δολαρίου "$". Έτσι για μια μεταβλητή που θα ονομάζεται var, θα είναι βαθμωτή και θα πάρει την τιμή 3.14 αρκεί να γράψουμε:
$var=3.14
Βλέπουμε πως η απόδοση τιμής σε μεταβλητή γίνεται με το σύμβολο του "=". Πολύ σημαντικό σε αυτή τη διαδικαία απόδοσης είναι να τηρείται η σωστή διάταξη. Αυτή είναι:
ονομα μεταβλητης = τιμή
και ποτέ το αντίθετο. Θυμηθείτε πως η χρήση του "=" δεν αντιστοιχεί εδώ σε ισότητα αλλά σε μια λογική διαδικασία που το εκφραστικό της ανάλογο είναι "κάνε την τιμή της μεταβλητης $var ίση με 3.14".
Με απολύτως ανάλογο τρόπο η απόδοση μιας σειράς χαρακτήρων σε μια μεταβλητή καθορίζει τον τύπο αυτής της μεταβλητής ως string. Π.χ.
$dna='agtatcgatcgatgcatg';
$protein=”KMYVNDDESPLK”;
Για να δείτε την διαδικασία στην πράξη γράψτε το παρακάτω μικρό πρόγραμμα και εκτελέστε το:
#! /usr/bin/perl use warnings; $dna="agct"; print $dna,"\n"; exit;
Ένα βασικό στοιχείο της απόδοσης τιμής σε μεταβλητή είναι ότι δεν έχει "μνήμη". Η τιμή δηλαδή κάθε μεταβλητής είναι ανά πάσα στιγμή η τελευταία (πιο πρόσφατη) τιμή που της αποδόθηκε στο πρόγραμμα. Δοκιμάστε το παρακατω
#! /usr/bin/perl use warnings; $dna="agct"; print $dna,"\n"; $dna="AAAAAAA"; print $dna,"\n"; exit;
Η χρήση των εισαγωγικών είναι σημαντική τόσο για τη διαδικασία εκχώρησης (απόδοσης) τιμής σε μεταβλητές όσο και για την εκτύπωσή τους. Τα εισαγωγικά στην Perl είναι δύο τύπων:
α. διπλά " "
β. μονα ' '
Η βασική τους διαφορά είναι πως ό,τι περικλείεται απο διπλά εισαγωγικά “μεταφράζεται” μέσω των εντολών της Perl, ενώ ό,τι βρίσκεται μέσα σε μονά μένει ως έχει.
Δοκιμάστε π.χ. να γράψετε σε ένα πρόγραμμα τα παρακάτω:
#! /usr/bin/perl use warnings; $dna="agcttg"; $protein="KMYVNDDESPLK"; print "$dna\n"; print '$protein\n'; exit;
Βλέπετε πως το αποτέλεσμα της πρώτης εκτύπωσης είναι το αναμενόμενο. Τυπώνεται η τιμή της μεταβλητής $dna ακολουθούμενη από μια αλλαγή γραμμής. H διαδικασία αυτή (της ενσωμάτωσης μιας μεταβλητής) λέγεται interpolation. Η επόμενη γραμμή όμως δεν τυπώνει όπως θα περιμέναμε την τιμή της $protein παρά στην κυριολεξία τη σειρά χαρακτήρων που τη συνθέτουν "$protein" και τους δύο χαρακτήρες \n. Τα μονά εισαγωγικά χρησιμοποιούνται κατ' αυτόν τον τρόπο μόνο σε περιπτώσεις που θέλουμε μια "αυτολεξεί" μεταφορά ενός string στην εκτύπωση. Αντίθετα τα διπλά εισαγωγικά μπορούν να "αντιληφθούν" πιο κομμάτι εντός τους αναφέρεται σε μια μεταβλητή και να τυπώσουν την τιμή της μεταβλητής αυτής αντί απλώς για το όνομά της. Για παράδειγμα:
#! /usr/bin/perl use warnings; $word1="I"; $word2="you"; $sentence="$word1 love $word2.";
print $sentence,"\n";
exit;
Σε ό,τι αφορά την χρήση τους στην απόδοση τιμών ωστόσο τα εισαγωγικά δεν έχουν διαφορά. Έτσι οι συντάξεις:
$dna='agtatcgatcgatgcatg';
$protein=”KMYVNDDESPLK”;
δεν έχουν διαφορές. Η χρήση και των δύο εναλλακτικών προσφέρει τη δυνατότητα να να εισάγει κανείς σε μια μεταβλητή και εισαγωγικά κάποιου τύπου.
Τι είναι; Oι διαχωριστές αρχείων είναι χαρακτήρες που χρησιμοποιούμε για να ξεχωρίσουμε τα στοιχεία μιας εντολής.
Διαχωριστές στοιχείων εντολών: Το κόμμα είναι ο πιο βασικός διαχωριστής. Πχ
print $dna , $protein, $whatever;
Διαχωριστές στοιχείων output. Πιο κοινοί διαχωριστές είναι το κενο " ", το tab (\t) και η αλλαγή γραμμής (\n). Π.χ.
print $dna, "\t", $protein, "\t", 5, "\n";
Χαρακτήρες διαφυγής είναι χαρακτήρες και συνδυασμοί τους που χρησιμοποιούμε για να ξεφεύγουμε από τους κανόνες ενσωμάτωσης (interpolation). Για παράδειγμα έστω ότι θέλουμε να τυπώσουμε την φράση:
Ηe told us: "Our next record will be called 'The blue Album'"
Πώς θα γράψουμε την εντολή print για αυτή τη φράση που περιέχει και μονά και διπλά εισαγωγικά; Αν την τοποθετήσουμε μέσα σε μονά εισαγωγικά θα υπάρξει πρόβλημα στο σημείο (called 'The) και αν την τοποθετήσουμε εντός διπλών θα υπάρξει πρόβλημα στο (us: "Our). O μόνος τρόπος είναι να ζητήσουμε από την Perl να αγνοήσει τα σύμβολα που εμείς θέλουμε να παραμείνουν ως οι χαρακτήρες που είναι. Αυτό το πετυχαίνουμε με τους χαρακτήρες διαφυγής κυριότερος εκ των οποίων είναι το backslash \.
H χρήση του backslash στο παραπάνω παράδειγμα θα ήταν η εξής:
print "Ηe told us: \"Our next record will be called \'The blue Album\'\"";
Βλέπετε πως τοποθετούμε ένα \ ακριβώς πριν από τον κάθε χαρακτήρα τον οποίον θέλουμε να τυπωθεί ακριβώς όπως είναι. Η πράξη αυτή της "διαφυγής" ισχύει μόνο για έναν χαρακτήρα.
Μαθηματικά σύμβολα και Αριθμητικές πράξεις
H Perl υποστηρίζει όλες τις αριθμητικές πράξεις μεταξύ αριθμητικών μεταβλητών. Οι βασικές πράξεις όπως πρόσθεση, αφαίρεση, πολλαπλασιασμός και διαίρεση συμβολίζονται ως:
πρόσθεση: + ($a+$b)
αφαίρεση: - ($a-$b)
πολλαπλασιασμός: * ($a*$b)
διαίρεση: / ($a/$b)
Άλλες πράξεις είναι οι:
ύψωση σε δύναμη: **. Π.χ. $a**2 (ύψωση του $a στο τετράγωνο)
υπόλοιπο διαίρεσης: % Π.χ. αν $a=18; $a%5=3 (το υπόλοιπο της διαίρεσης του 18/5 είναι 3)
Ιδιαίτερη προσοχή χρειάζεται στη σειρά προτεραιότητας. Αυτή είναι: **, %, *, /, +, - που σημαίνει ότι σε μια πολύπλοκη αριθμητική παράσταση πρώτα θα εκτελεστούν οι δυνάμεις, μετά οι πολλαπλασιασμοί και διαιρέσεις και στο τέλος οι προσθαφαιρέσεις. Για το λόγο αυτό η καλύτερη πρακτική είναι να χρησιμοποιούνται παρενθέσεις. π.χ.:
$P=($a+$b)/2**(3+4)
Σε αυτήν την περίπτωση η εκτέλεση εκτελούνται πρώτα οι προσθέσεις και μετά η πράξη 2**7. Στη συνέχεια διαιρείται το ($a+$b) προς (2**7). Αν θέλουμε να γίνει πρώτα η διαίρεση θα πρέπει να γράψουμε:
$P=(($a+$b)/2)**(3+4)
Συναρτήσεις αριθμητικών μεταβλητών
Εκτός από τις απλές και σύνθετες αριθμητικές πράξεις υπάρχουν και αρκετές χρήσιμες συναρτήσεις για αριθμητικές μεταβλητές. Οι περισσότερες συναρτήσεις της Perl εκτελούνται με την ακόλουθη σύνταξη:
$newvariable=function($variable)
Μερικές κοινές αριθμητικές συναρτήσεις είναι:
Απόλυτη τιμή: abs($a), (πχ $a=-5, abs($a)=5 )
Ακέραιο μέρος: int($a), (πχ $a=3.14, int($a)=3 )
Λογάριθμος: log($a), (προσοχή είναι ο φυσικός λογάριθμος δηλαδή ο λογάριθμος με βαση e)
Τετραγωνική ρίζα: sqrt($a)
Ημίτονο: sin($a)
Συνημίτονο: cos($a)
Περισσότερες συναρτήσεις μπορεί κανείς να βρεί αναζητώντας το αρχείο βοήθειας της Perl (http://perldoc.perl.org/perl.html)
Αλλάζοντας τιμή στην μεταβλητή με βήμα (increments)
Αύξηση κατά ένα (1): ++. $count++. Πχ:
$count=1; $count++; print $count, "\n";
Αύξηση κατά οποιονδήποτε αριθμό: +=αριθμός
$count=1; $count+=10; print $count, "\n";
Το ίδιο ισχύει για μείωση (-=), πολλαπλασιασμό (*=) και διαίρεση (/=), ύψωση σε δύναμη (**=) αλλά και την "τέλεση" πράξεων σε strings (βλ. παρακάτω).
Όπως οι αριθμητικές μεταβλητές, έτσι και οι μεταβλητές συμβόλων strings έχουν μια σειρά από λειτουργίες και συναρτήσεις που μας επιτρέπουν απλούς και πολύπλοκους χειρισμούς. Στα πλαίσια βιολογικών εφαρμογών οι χειρισμοί σε strings έχουν πρωταρχική σημασία. Κάποιες χαρακτηριστικές πράξεις και συναρτήσεις σε strings είναι οι παρακάτω:
Σύνδεση (concatenation)
Είναι η διαδικασία κατά την οποία ενώνουμε δύο σειρές χαρακτήρων σε μία. Ο τελεστής της είναι η τελεία “.”
Δοκιμάστε:
$DNA="AGCT"; $protein="KMYR"; $all=$DNA.$protein; print $all,"\n";
Η πράξη της σύνδεσης μπορεί να συνδυαστεί με το "=" με τον ίδιο τρόπο με τον οποίο γίνεται η αύξηση (increment) σε αριθμητικές μεταβλητές. Έτσι αν θέλουμε απλώς να προσθέσουμε κάτι στο τέλος μιας υπάρχουσας μεταβλητής string δεν έχουμε παρά να χρησιμοποιήσουμε τον τελεστή ".=":
$DNA="AGCT"; $protein="KMYR";
$all.=$DNA; # adds $DNA at the end of a null string ('') called $all $all.=$protein; # adds $protein at the end of $all which by now contains $DNA print $all,"\n"; # same output as above
Επανάληψη
Mια σειρά χαρακτήρων μπορεί να επαναληφθεί όσες φορές καθορίζει ένας αριθμός, με έναν τρόπο ανάλογο του πολλαπλασιασμού. Tελεστής είναι το "x" ακολουθούμενο από τον αριθμό που δηλώνει το πλήθος των επαναλήψεων.
Δοκιμάστε:
print ”Go!” x3, “\n”;
Μήκος σειράς (string)
Ο υπολογισμός του μήκους ενός string είναι μια διαδικασία που μπορεί να χρειαστεί να κάνουμε πολύ συχνά. Η συνάρτηση που την επιτελεί είναι η length(). Oι εντολές:
$dna="AGCTTG"; $l=length($dna); print $l,"\n";
Επιστρέφουν στην οθόνη την αριθμητική τιμή 6 που είναι το μήκος του string σε αριθμό χαρακτήρων.
Eξαγωγή στοιχείων από string
Συχνά μας ενδιαφέρει το μέρος μόνο από ενα μεγαλύτερο string και επιθυμούμε να εξάγουμε ένα τμήμα ενός string σε μια νέα μεταβλητή χωρίς να μεταβληθεί η αρχική. Η συνάρτηση με την οποία μπορούμε να κάνουμε κάτι τέτοιο είναι η substr() (από το substring). H σύνταξη της substr() χρειάζεται προσοχή γιατί δέχεται τρία ορίσματα:
substr($string, offset, length)
Όπου $string είναι η scalar μεταβλητή από την οποία θα εξαχθεί ένα string που θα ξεκινά στην θέση offset+1 με μήκος length. Χρειάζεται προσοχή στο οffset το οποίο είναι μετατοπισμένο κατά 1 διότι η αρίθμηση των θέσεων στην Perl ξεκινά από το 0 (zero-based), ένα σημείο στο οποίο θα επανέλθουμε όταν θα συζητήσουμε για πίνακες. Παράδειγμα χρήσης της substr() η σειρά εντολών:
$dna="AGCCCTGAAG"; $frag=substr($dna, 2, 3); print $frag,"\n";
Eπιστρέφει τη σειρά χαρακτήρων "CCC" δηλαδή τη σειρά μήκους τριών χαρακτήρων που ξεκινά από τη θέση 3 (2+1).
Αντιστροφή σειράς
H συνάρτηση για την αντιστροφή ενός string με βάση τη διαδοχή των χαρακτήρων του είναι η reverse(), που χρησιμοποιείται ως εξής:
$DNA="ATTTGCACACGTGCG"; $rev=reverse($DNA); print $rev,"\n";
που επιστρέφει το string: GCGTGCACACGTTTA.
Μετατροπή σε κεφαλαία/μικρά
Γίνεται με την uc()/lc(), που χρησιμοποιούνται ως εξής:
$DNA="attcgccaca"; $upper=uc($DNA);
$lower=lc($upper) print $DNA,"\n",$upper,"\n",$lower,"\n";
Εύρεση θέσης σε string
H συνάρτηση για την εύρεση της θέσης ενός χαρακτήρα εντός ενός string με βάση τη διαδοχή των χαρακτήρων του είναι η index(string,character), που χρησιμοποιείται ως εξής:
$string = 'AKLIMPOLLDDKAS'; $char = 'L'; $result = index($string, $char); print "Result: $result\n";
που επιστρέφει την τιμή 2. Δώστε προσοχή στην αρίθμηση των χαρακτήρων που ξεκινάει από το 0. Δοκιμάστε την εκτέλεση για έναν χαρακτήρα που δεν υπάρχει (π.χ. Χ). Επίσης σημειώστε ότι θα αναφέρεται πάντα μία θέση που θα αντιστοιχεί στην πρώτη εμφάνιση του χαρακτήρα μέσα στο string.
H index(string,char) μπορεί να εμπλουτιστεί και με offset δηλαδή με μετατόπιση του σημείου έναρξης της αναζήτησης το οποίο δηλώνεται ως εξής: index(string,char,offset). Προσπαθήστε να μαντέψετε το output του παρακάτω προγράμματος.
$string = 'AKLIMPOLLDDKAS'; $char = 'L'; $result = index($string, $char, 3); print "Result: $result\n";
Ευρεση και Αντικατάσταση
Ανάμεσα στις πιο συχνά χρησιμοποιούμενες λειτουργίες της Perl για βιολογικές εφαρμογές είναι η εύρεση και αντικατάσταση στοιχείων χαρακτήρων σε μεγαλύτερες μεταβλητές strings. H εύρεση εμπεριέχει ένα στοιχείο λογικού ελέγχου για τους οποίους θα δούμε περισσότερα σε επόμενα κεφάλαια. Για τις ανάγκες μιας απλής αναζήτησης στοιχείων σε ενα string η σύνταξη της εντολής είναι η παρακάτω:
$string~/pattern/
όπου το "pattern" είναι η σειρά των χαρακτήρων που αναζητούμε εντός της μεταβλητής $string χωρίς εισαγωγικά κλπ.
H εντολή αυτή θα πρέπει να συνδεθεί με έναν λογικό έλεγχο για τους οποίους θα δούμε περισσότερα στη συνέχεια.
Σε ό,τι αφορά τη λειτουργία αντικατάστασης, της εύρεσης δηλαδή ενός substring και της αντικατάστασής του από ένα άλλο η σύνταξη είναι η εξής:
$RNA =~ s/T/U/g;
Στο παρακάτω παράδειγμα ο τελεστής αντικατάστασης είναι το s/ / / και εισάγεται με τον συνδέτη "=~". Η πιο πάνω σύνταξη σημαίνει "να αντικατασταθεί το Τ απο U μέσα στο $RNA". Ο χαρακτήρας "g" στο τέλος της εντολής σημαίνει "global" δηλαδή η αντικατάσταση να γίνει σε όλο το $string. Παράλειψη του "g" θα οδηγήσει σε αντικατάσταση μόνο της πρώτης εμφάνισης του Τ. Δοκιμάστε:
$RNA="ATGCTGGGACCC"; $RNA =~ s/T/U/; print $RNA,"\n"; $RNA =~ s/T/U/g; print $RNA,"\n";
Συγκρίνετε τις δύο εκτυπώσεις. Τώρα δοκιμάστε την παρακάτω σειρά εντολών:
$RNA="AtGCTGGGACCC"; $RNA =~ s/T/U/g; print $RNA,"\n"; $RNA =~ s/T/U/ig; print $RNA,"\n";
Σε αυτήν την περίπτωση η μεταβλητή $RNA αλλάζει (μεταβάλλεται) ανάλογα με την ύπαρξη υποσημείωσης (i) ή όχι. Το i και το g πιο πριν λέγονται flags και τροποποιούν την εφαρμογή της αντικατάστασης s///. Το g κάνει συνολική αντικατάσταση ενώ το i (ignore case) κάνει αντικατάσταση ανεξαρτήτως αν το στοιχείο που αναζητείται είναι σε πεζά ή κεφαλαία.
Μετάφραση
Πολλές φορές επιθυμούμε να κάνουμε μια σειρα από αντικαταστάσεις που είναι αδύνατον να γίνουν ακόμα και με μια σειρά από εντολές s///. Για παράδειγμα σκεφτείτε πως θα παίρνατε από μια αλληλουχία DNA την συμπληρωματική της κάνοντας όλα τα Τ->Α, τα Α->Τ, τα G->C και τα C->G. Τέτοιου τύπου συνολικές αντικαταστάσεις μπορούν να επιτευχθούν με μία εντολή που λέγεται tr και σημαίνει transliteration. H σύνταξή της είναι η εξής:
$comp =~ tr/ACGT/TGCA/;
Kαι εδώ χρησιμοποιείται ο τελεστής σύνδεσης =~ και η δομή tr/κάτι/κάτι αλλο/. Στην περίπτωση του tr το πρώτο μοτίβο μεταξύ του πρώτου ζεύγους // περιέχει τους χαρακτήρες που θα αντικατασταθούν, ενώ ανάμεσα στο δεύτερο ζεύγος // περικλείονται ίσος αριθμός χαρακτήρων που αντικαθίστανται ένα προς ένα. Η σειρά των εντολών:
$DNA="AGCTGTGCCTG"; $comp=$DNA; $comp =~ tr/ACGT/TGCA/; print $DNA,"\n"; print $comp,"\n";
Τυπώνει το $DNA και το συμπληρωματικό του τμήμα, το ένα κάτω από το άλλο.