| [הקודם : סוגי משתנים והגדרתם] | [חזרה לתוכן העניינים] | [הבא : טיפול במחרוזות] |
כמו שכבר הסברנו בפרק סוגי משתנים, סעיף משתנים סקלרים, בפרל 0, המחרוזת הריקה ("") ו-undef הם שקר, כל דבר אחר זה אמת.
פרל תומכת בכל האופרטורים הבוליאניים המוכרים, אם בסגנון C, (&&, ||, !) או בסגנון פסקל. (And, Or, Not)
אופרטורים לוגיים:
| פעולה | אופרטור פסקל | אופרטור C |
|---|---|---|
| And | $a and $b | $a && $b |
| Or | $a or $b | $a || $b |
| Not | not $a | ! $a |
| פעולה | אופרטור מחרוזת | אופרטור מספר |
|---|---|---|
| האם שווה | $a eq $b | $a == $b |
| האם לא שווה | $a ne $b | $a != $b |
| האם גדול | $a gt $b | $a > $b |
| האם גדול-שווה | $a ge $b | $a >= $b |
| האם קטן | $a lt $b | $a < $b |
| האם קטן-שווה | $a le $b | $a <= $b |
| השוואה | $a cmp $b | $a <=> $b |
כן, ניגזרותיה. כלל גדול בפרל אומר, "יש יותר מדרך אחת לעשות את זה". ובפרט, יש יותר מדרך אחת לעשות if. אבל נתחיל ברגילה, בסדר? הנה:
if (condition1) {
Set of commands…
} elsif (condition2) {
Set of commands…
} else {
Set of commands…
}
אלה שני משפטי תנאי רגילים, משורשרים.
יש גם וורסיות אחרות של משפט ה-if. הפקודות הבאות זהות:
if ($m==3) {
print “Avukado”;
}
print “Avukado” if ($m==3);
print “Avukado” unless ($m != 3);טוב, פה פרל זהה לשפת C. כמעט. הנה דוגמא:
while ($line=<>) {
$count_lines++;
if (substr($line,1) eq ’#’) {
next;
}
if ($line eq ”End\n”) {
last;
}
print $line;
}
אז מה יש לנו כאן? בשורה הראשונה יש את אופרטור ה-<>. זה אופרטור שקורא שורה מה-stdin, ומציב אותה לתוך $line. אם לא נשארו שורות - הוא יחזיר undef, מה שיתן שקר, והלולאה תסתיים. נסביר בפרק מאוחר יותר על האופרטור הזה.
מיד אחרי שקראתי את השורה, אני סופר אותה. שיהיה. אח"כ אני בודק האם התו הראשון של השורה הוא "#". אם כן, אזי אני מדלג ועובר לשורה הבאה. אם השורה היא “End”, הסתיים הקובץ, ואני שובר החוצה מהלולאה. ובסוף, אם לא קרה שום דבר דרסטי, אני מדפיס את השורה לפלט הסטנדרטי (STDOUT).
לולאת for היא בהחלט כמו המקבילה של ב-C. כמעט.
my ($m, $i);
$m=1;
for ($i=1; $i<5; $i++) {
$m = $m*$i;
}יש ללולאות גם פקודות בקרה:
my ($m, $i, $j) = (0,0,0);
for ($i=1, $m=1; $i<5; $i++) {
$j++;
redo unless ($j>=$i);
if ($i+$m>30) {
last;
}
next if ($i==1);
$m=$m*$i/$j;
}
פקודת next מקפיצה את ההרצה לסוף הלולאה, ומתחילה סיבוב חדש של הלולאה. כלומר, $i מתקדם באחד, והלולאה שוב מתחילה לרוץ. פקודת last שוברת את הלולאה, והתוכנית ממשיכה לרוץ. פקודת redo היא פקודה מיוחדת. היא מקפיצה את ההרצה לתחילת הלולאה. זה אומר ש-$i לא מתקדם, אבל $j שממוקם שורה מתחתיו, כן יתקדם. לא ראיתי את זה בשום שפה אחרת, אבל דוגמא מעניינת להוראה תמצאו בפרק על טיפול בקבצים.
מקרה אחר של for היא ה-foreach. הנה דוגמא:
foreach $count (10,9,8,7,6,5,4,3,2,1,"BOOM!") {
print "$count\n";
}בכל סיבוב של הלולאה, $count מקבל אחד מהערכים של הרשימה שאחריו, שמודפס בפקודה. אם הרשימה היא בעצם מערך, אזי $count בעצם נהפך לערך. לא נתמקד במוזרות הזאת, רק נראה דוגמא:
my @arr=(1,2,3,4,5);
foreach $val (@arr) {
$val=$val*2+1;
}כאן הערכים בתוך המערך @arr ישתנו. מוזר, אך אמיתי ויעיל.
כשפרל בודק משפטים לוגיים, הוא עושה זאת בחלקים. לדוגמא, אם יש את הביטוי הבא:
$x or $m++
אם $x הוא אמת, אזי $m לא יקודם. זה בגלל שפרל כבר יודע שהערך של הביטוי הוא אמת, ואין לו צורך לבדוק את חלקו השני.
משתמשים בזה בפרל המון, פשוט במקום לעשות if. הנה פתיחת קובץ טיפוסית:
open(my $fh, ">", "zorba.txt") or die “Cann’t open that file!\n”;
הפקודה open פותחת קובץ, בשם zorba.txt, תחת המשתנה $fh. אם היא מצליחה, היא מחזירה אמת, ואז פרל לא ממשיכה לבדוק את התנאי. אם open מחזירה שקר, אז פרל ממשיך לבדוק את התנאי, ומגיע לפקודה die "string", שמוציאה את הודעת השגיאה ועוצרת את ההרצה.
נכון, זה יכול להיות מכוער, ואפשר לכתוב בעזרת זה דברים לחלוטין בלתי קריאים. אבל זה פרל, ואפשר להשתמש בזה במקום המון פקודות if. תגיד בעצמך מה יותר קריא, הפקודה שלמעלה או פקודה מקבילה בסגנון C?
if (open(FH, ">", "zorba.txt")==0) {
die "Cann't open that file!\n";
}בקיצור, אחרי שמתרגלים לזה, זה נחמד.
כרגע יש לנו, כאבני בנין את המשתנים, ואת מבני הבקרה. התוכנית עכשיו יכולה להיות קצת יותר אינטילגנטית. (אבל לא בהרבה)
#!/usr/bin/perl -w
use strict;
my ($key, $val);
my %h;
while ($key=<>) {
defined($val=<>) or die "Odd number of line?!\n";
chomp($key);
chomp($val);
$h{$key}=$val;
}
foreach $key (keys(%h)) {
print $key, "->", $h{$key}, ", ";
}
print "\n";
print $h{"message"}, "\n";
my $i ;
for ($i=1; $i<$h{"loop count"}; $i++) {
last if ($h{"loop count"}*2-$i<5);
print $h{"loop msg"}, "\n";
}
התוכנית משתמשת בפקודה שעדיין לא הזכרנו - chomp. זוהי פקודה שמורידה מהקלט את סימני סוף השורה. אם לא נשים אותה, התוכנית גם תעבוד, אבל נקבל כל מיני אזהרות. (בגלל שאנחנו משתמשים ב-"-w" בשורה הראשונה של התוכנית, שאומרת לו להזהיר אותנו) זה יקרה בכל פעם שננסה להשתמש בקלט כמספר, ואז הוא צריך לתרגם אותו למספר, ישמיט את סימני סוף השורה, יזהיר אותנו שהוא עשה את זה, אבל ימשיך לרוץ.
מה שהתוכנית עושה זה לקרוא קובץ, וכל זוג שורות להכניס בתור מפתח וערך לתוך טבלת האש. אח"כ היא מדפיסה את טבלת ההאש שהתקבלה, מדפיסה את הערך שתחת המפתח "message", ואז רצה בלולאה לפי "loop count" ומדפיסה את "loop msg". קובץ קלט לדוגמא:
<Start input file> 5 Oops. loop count 17 And the winner is me. loop msg AhAhAhAh! message Resistance is futile <End input file>
שים לב שאין חשיבות לסדר הזוגות. ממילא הכל נשפך אח"כ לתוך האש ומתערבל שם. שים גם לב לכך שמספר השורות צריך להיות זוגי. אם הוא לא זוגי, (יכול להיות שהעורך שלך אוהב להוסיף שורה ריקה בסוף הקובץ) אז פשוט תוסיף בעצמך שורה ריקה, וכך יהיו לך שתי שורות ריקות בסוף הקובץ.
הרצת התוכנית: אם נקרא לקובץ הקלט פשוט "in3", לקובץ של הסקריפט "chap3.pl", אזי ביוניקס השורה הבאה תפעיל את הקובץ:
./chap3.pl <in3
בחלונות, בהנחה שפרל היא בנתיב החיפוש:
perl chap3.pl <in3
בהצלחה.
| [הקודם : סוגי משתנים והגדרתם] | [חזרה לתוכן העניינים] | [הבא : טיפול במחרוזות] |
נכתב ע"י שמואל פומברג, כל הזכויות שמורות © ראה פרק 1.5 לתנאי רשיון