# מ־awk ל־Perl אתם מכירים את `awk`. אתם חושבים במונחי `pattern { action }`, מפצלים כל שורה ל־`$1`, `$2`, `$3` בלי לשאול, סופרים דברים עם `a[key]++`, וממסגרים את כל המשימה עם `BEGIN { }` ו־`END { }`. Perl נכתבה בחלקה כ“awk, אבל גדולה יותר“ - כמעט כל מה שאתם עושים ב־awk יש לו צורת Perl ישירה, ואז Perl ממשיכה הלאה: מבני נתונים אמיתיים, ביטויים רגולריים מלאים, מודולים, ושפה שלא נגמר לה המקום כשהסקריפט גדל. הרעיון האחד שכדאי לקחת איתכם כבר מהשורה הראשונה: **Perl היא כמעט על־קבוצה של awk.** לולאת הרשומה, השדות, המערכים האסוציאטיביים, מילות המפתח `BEGIN`/`END`, `print` ו־`printf`, `length`/`substr`/`split` - כולם ממופים, לעיתים קרובות לפי *אותו שם*. מה שמשתנה הוא ששדות הופכים למערך אמיתי `@F` שאתם יכולים `push` ו־`pop`, המערך האסוציאטיבי הופך להאש Perl שאתם יכולים לקנן, ומנוע הביטויים הרגולריים הוא PCRE ולא POSIX ERE. מדריך זה פותח במיפויים החד־חד־ערכיים ומצביע על המקומות המעטים שבהם האנלוגיה דולפת. Every runnable example here was executed on `pperl`, a Rust reimplementation of Perl 5.42; the `# ...` comments show its real output. Start scripts with: ```perl use v5.42; ``` שורה אחת זו מפעילה את `strict`, את `warnings`, ואת הפונקציה המובנית `say` (כלומר `print` עם תו שורה חדשה נגרר), מערך התכונות המודרני המשמש לאורך כל הדרך. #### NOTE מתגי שורה־אחת ב־build הזה של pperl התאום הטבעי של awk ב־Perl הוא שורת־הקוד־האחת: `perl -ne`, `perl -ane`, ו־`perl -F, -ane`. מתגים אלה הם **perl5 5.42 תקני** ומוצגים לאורך מדריך זה כצורה האידיומטית. אך משפחת מתגי הלולאה המשתמעת (`-n`, `-p`, `-a`, `-F`, `-i`, `-l`) **עדיין אינה מזוהה על ידי build זה של `pperl`** - רק `-e` מזוהה. לכן דוגמאות שורת־הקוד־האחת שלהלן מוצגות *ללא* פלט, וכל אחת מהן מצומדת לצורת סקריפט־מלא עם לולאה מפורשת (`while (<$fh>) { ... }`) ש**אכן** רצה על `pperl` היום ונושאת את הפלט המאומת. השתמשו בצורת הסקריפט המלא עד שהמתגים ייכנסו. ## כיצד לקרוא את זה - [לולאת השורה/רשומה]() - ה־`{ ... }` המשתמע של awk הופך ל־`while (<$fh>)` ו־`$_`. - [שדות ופיצול]() - `$1`/`$NF`/`NF`/`FS` הופכים ל־`@F`, `$F[0]`, `split`, `-F`. - [ביטויים רגולריים והחלפה]() - `gsub`/`sub`/ `match` הופכים ל־`s///`/`=~`, על־קבוצה ממש. - [כתובות וטווחים]() - `/re/`, `cond { }`, ו־`/a/,/b/` הופכים ל־`if` בתחביר סיומת ול־flip-flop. - [קלט/פלט, צינורות, עריכה במקום]() - `getline`, הפניה־מחדש, ו־`-i`. - [שורות־קוד־אחת ומתגים]() - `-n`, `-a`, `-F`, `BEGIN`/`END`. - [זרימת בקרה]() - `next`, `for`, צורות הסיומת. - [משתנים ונתונים]() - מערכים אסוציאטיביים הופכים להאשים, המיפוי המשמח. - [מלכודות בהגעה מ־awk]() - סרקו לפני שאתם כותבים. ## לולאת השורה/רשומה awk מריצה את התוכנית שלכם פעם אחת לכל רשומת קלט, כשהרשומה ב־`$0` והפעולה ב־`{ ... }`. המקבילה של Perl היא לולאה מפורשת שבה הרשומה ב־`$_`, משתנה הנושא המשתמע. המתג `-n` משחזר את ”הרץ בלוק זה לכל שורה“ של awk; ה־`NR` של awk (מספר הרשומה) הוא ה־`$.` של Perl. ```awk awk '{ print }' input.txt ``` ```perl perl -ne 'print' input.txt ``` הצורה הניתנת־להרצה, של סקריפט מלא, של אותה לולאה - זו שרצה על `pperl` היום - פותחת את הקובץ ועוברת עליו במפורש. `$_` היא הרשומה הנוכחית, בדיוק כמו ה־`$0` של awk: ```perl use v5.42; open my $fh, '<', '/tmp/scores.txt' or die "open: $!"; while (<$fh>) { # each line lands in $_, like awk's $0 chomp; say "line $. : $_"; # $. is awk's NR } # line 1 : alice 85 90 # line 2 : bob 70 60 # line 3 : carol 95 100 # line 4 : alice 50 55 ``` (קובץ הקלט החזיק `alice 85 90`, `bob 70 60`, `carol 95 100`, `alice 50 55`.) המלכודת: שורה הנקראת עם `<$fh>` שומרת על תו השורה החדשה הנגרר שלה, בניגוד ל־`$0` של awk, שממנו מופרד מפריד הרשומה. קראו ל־`chomp` כדי לקצץ אותו (chomp הוא הדבר הקרוב ביותר ל“awk כבר הסירה עבורכם את תו השורה החדשה“). מספר הרשומה הוא `$.` = ה־`NR` של awk; כשאתם קוראים מספר קבצים עם `<>`, `$.` ממשיך לספור לאורכם, כך שאיפוס ה־`FNR` של awk (מונה לכל קובץ) הוא דבר שאתם מסדרים בעצמכם על ידי בדיקת `eof`. ## שדות ופיצול זה הלב של awk, ו־Perl נותנת לכם את אותה תמונה עם תפנית אחת: השדות חיים במערך אמיתי `@F`, כך שה־`$1` של awk הוא ה־`$F[0]` של Perl (מבוסס־אפס), `$0` הוא `$_`, ו־`NF` הוא הספירה `scalar @F`. תחת המתג `-a` Perl מפצלת אוטומטית כל שורה אל `@F` בדיוק כפי ש־awk מפצלת אוטומטית אל `$1..$NF`; המקבילה הניתנת־להרצה היא `split` מפורש אחד. ```awk awk '{ print $1, NF }' input.txt # first field, field count awk -F, '{ print $1 }' input.txt # comma separator (FS) ``` ```perl perl -ane 'print "$F[0] @{[scalar @F]}\n"' input.txt # -a fills @F perl -F, -ane 'print "$F[0]\n"' input.txt # -F sets the split pattern ``` צורת הסקריפט המלא עושה את הפיצול בעצמה. `split` חשוף ללא ארגומנטים מפצל את `$_` על רווחים לבנים ומשמיט רווחים מובילים - בדיוק ה־`FS` של ברירת המחדל של awk: ```perl use v5.42; open my $fh, '<', '/tmp/scores.txt' or die "open: $!"; while (<$fh>) { my @F = split; # awk's automatic field split say "$F[0] has ", scalar(@F) - 1, " scores"; # $F[0]=$1, @F=NF } # alice has 2 scores # bob has 2 scores # carol has 2 scores # alice has 2 scores ``` חשבון בין שדות הוא פעולת awk היומיומית `print $1, $2+$3`, והוא נקרא כמעט זהה: ```perl use v5.42; open my $fh, '<', '/tmp/scores.txt' or die "open: $!"; while (<$fh>) { my @F = split; say "$F[0]: ", $F[1] + $F[2]; # awk: print $1, $2+$3 } # alice: 175 # bob: 130 # carol: 195 # alice: 105 ``` ה־`$NF` של awk (השדה האחרון) הוא האינדקס השלילי `$F[-1]` של Perl, ו־`FS` שאינו ברירת המחדל הוא ארגומנט התבנית ל־`split`: ```perl use v5.42; open my $fh, '<', '/tmp/data.csv' or die "open: $!"; # alice,85,90 ... while (<$fh>) { chomp; my @F = split /,/; # awk -F, say $F[-1]; # awk's $NF: last field } # 90 # 60 # 100 ``` כדי לחבר שדות בחזרה עם מפריד (ה־`OFS` של awk), קבעו את `$,` (מפריד שדה הפלט ש־`print`/`say` מכניס בין ארגומנטי הרשימה שלו): ```perl use v5.42; open my $fh, '<', '/tmp/data.csv' or die "open: $!"; while (<$fh>) { chomp; my @F = split /,/; local $, = "|"; # OFS say @F; # join the list with OFS } # alice|85|90 # bob|70|60 # carol|95|100 ``` המלכודת: שדות הם **מבוססי־אפס**. ה־`$1` של awk הוא `$F[0]`, `$2` הוא `$F[1]`, ו־`$0` (הרשומה כולה) הוא `$_`, לא איבר של `@F`. `NF` הוא `scalar @F` (או `$#F + 1`); השדה האחרון הוא `$F[-1]`, לא `$F[NF]`. ו־`split` עם **רווח אחד כמחרוזת** (`split ' '`) הוא מצב הרווח־הלבן־וקיצוץ המיוחד; `split / /` (ביטוי רגולרי עם רווח אחד) הוא מילולי ו *אינו* מקצץ רווחים מובילים. `split` פשוט ללא ארגומנט הוא מצב ברירת המחדל של awk שאתם רוצים רוב הזמן. ## ביטויים רגולריים והחלפה ה־`sub`, `gsub`, `match`, ו־`~` של awk ממופים כולם אל תחביר הביטויים הרגולריים היחיד של Perl: `=~` קושר תבנית למחרוזת, `s///` מחליף, `s///g` הוא גלובלי (`gsub` מול `sub` של awk). מנוע Perl הוא PCRE, על־קבוצה ממש של POSIX ERE של awk, כך שכל תבנית awk עובדת ו־Perl מוסיפה הפניות לאחור, lookaround, לכודות בעלות שם, ואת הדגלים `/e`, `/r`, `/x` של־awk אין מקבילה אליהם. ```awk awk '/^alice/ { sub(/alice/, "ALICE"); print }' input.txt ``` ```perl perl -ne 'if (/^alice/) { s/alice/ALICE/; print }' input.txt ``` צורת הסקריפט המלא: ```perl use v5.42; open my $fh, '<', '/tmp/scores.txt' or die "open: $!"; while (<$fh>) { next unless /^alice/; # awk: /^alice/ { ... } s/alice/ALICE/; # awk: sub(/alice/, "ALICE") (first match) print; } # ALICE 85 90 # ALICE 50 55 ``` השתמשו ב־`s///g` עבור ה־`gsub` של awk (כל התאמה), וקבוצות לכידה נוחתות ב־`$1`, `$2` בדיוק כפי שה־`match` של awk ממלא את `RSTART`/`RLENGTH` בתוספת מערך ה־`gawk`. הדגל `/e` מריץ **Perl שרירותי** בהחלפה, מה ש־awk אינה יכולה לעשות: ```perl use v5.42; my $s = "items: 3 and 4"; (my $t = $s) =~ s/(\d+)/$1 * 10/ge; # /e: replacement is Perl code say $t; # items: 30 and 40 ``` `length`, `substr`, `index`, ופונקציות האותיות הגדולות/קטנות ממופות לפי שם - שימו לב לאינדוקס: ```perl use v5.42; my $s = "alice"; say length $s; # 5 (awk length($s)) say substr $s, 0, 3; # ali (awk substr($s,1,3) - awk is 1-based!) say uc $s; # ALICE (awk toupper($s)) ``` המלכודת: `substr` הוא **מבוסס־אפס** בעוד ש־`substr` של awk הוא מבוסס־אחד, כך ש־`substr($s,1,3)` של awk הוא `substr($s,0,3)` של Perl. ו־`s///` עורך את היעד שלו במקום ומחזיר את **ספירת** ההחלפות, לא את המחרוזת החדשה - כך ש־`my $new = ($s =~ s/a/b/)` שם מספר ב־`$new`. העתיקו תחילה (`(my $t = $s) =~ s/.../.../`) או השתמשו בדגל `/r` כדי לקבל מחרוזת רעננה. מחלקות תווים של POSIX (`[[:digit:]]`) עובדות, אך הקיצורים של Perl (`\d`, `\w`, `\s`) קצרים יותר ומה שתראו בקוד Perl. ## כתובות וטווחים כלל awk הוא `pattern { action }`: הפעולה רצה רק על רשומות התואמות את התבנית. ב־Perl תבנית זו היא פשוט תנאי על המשפט - `if` בתחביר סיומת הבודק את `$_`. `/re/` חשוף תואם כנגד `$_`, בדיקה מספרית משתמשת ב־`$.` (ה־`NR` של awk), והטווח `/start/,/end/` של awk הוא אופרטור ה־**flip-flop** של Perl, `/start/ .. /end/`. ```awk awk 'NR==2' input.txt # print record 2 awk '/banana/' input.txt # print matching records awk '/bob/,/carol/' input.txt # range, inclusive ``` ```perl perl -ne 'print if $. == 2' input.txt perl -ne 'print if /banana/' input.txt perl -ne 'print if /bob/ .. /carol/' input.txt ``` ה־flip-flop של הסקריפט המלא, אמת מהשורה התואמת את התבנית השמאלית עד השורה התואמת את הימנית, כולל - בדיוק טווח שתי־התבניות של awk: ```perl use v5.42; open my $fh, '<', '/tmp/scores.txt' or die "open: $!"; while (<$fh>) { print if /bob/ .. /carol/; # awk: /bob/,/carol/ } # bob 70 60 # carol 95 100 ``` המלכודת: `pattern` חשוף ללא פעולה ב־awk משמעו ”הדפס את הרשומה“; ב־Perl הלולאה מפורשת, כך שאתם כותבים את ה־`print` (או `say`) בעצמכם. ובבדיקה בוליאנית `..` הוא אופרטור ה־flip-flop (טווח), **לא** אופרטור טווח־הרשימה (`1 .. 10` בונה רשימה). Perl מבחינה ביניהם לפי הקשר: בעמדה הסקלרית של `if`, `..` הוא בורר טווח־השורות בעל־המצב המשקף את `addr1,addr2` של awk. ## קלט/פלט, צינורות, עריכה במקום awk קוראת אוטומטית כל קובץ הנקוב בשורת הפקודה שלה ויש לה `getline` לקריאות מפורשות. ה־`<>` של Perl (אופרטור היהלום) קורא כל קובץ ב־`@ARGV` בתורו - אותה ברירת מחדל - ו־`<$fh>` הוא ה־`getline` המפורש. כתיבה לפקודה או קריאה ממנה (`print | "cmd"` ו־`"cmd" | getline` של awk) היא מטפל קובץ של צינור. ```awk awk '{ print > "out.txt" }' input.txt # redirect output awk '{ print | "sort" }' input.txt # pipe to a command ``` ```perl use v5.42; open my $out, '>', '/tmp/out.txt' or die "write: $!"; open my $in, '<', '/tmp/scores.txt' or die "read: $!"; while (<$in>) { print {$out} $_; # awk: print > "out.txt" } close $out; ``` לצינורות, `open my $fh, '|-', 'sort'` כותב לקלט הפקודה ו־`open my $fh, '-|', 'ls', '-l'` קורא את פלט הפקודה - ה־`| "cmd"` של awk בשני הכיוונים. ל־awk אין עריכה־במקום מובנית; אתם נשענים על העברת קובץ־`tmp` או על `gawk -i inplace` של GNU. Perl מאייתת זאת `-i` על שורת־קוד־אחת: ```perl perl -i -pe 's/red/crimson/' file.txt # edit in place ``` המקבילה הניתנת־להרצה היום היא קריאה־שינוי־כתיבה מפורשת - בלעו את השורות, המירו, כתבו חזרה - שזה בדיוק מה ש־`-i` עושה מתחת למכסה המנוע: ```perl use v5.42; my $path = '/tmp/inplace.txt'; # holds: red green blue open my $in, '<', $path or die "read: $!"; my @lines = <$in>; # slurp all lines (list context) close $in; s/e/E/g for @lines; # transform each line's $_ open my $out, '>', $path or die "write: $!"; print {$out} @lines; # write them back close $out; # file now holds: rEd / grEEn / bluE ``` המלכודת: `open` מחזיר שקר בכישלון במקום להפסיק, לכן הניב `or die "...: $!"` הוא חובה - `$!` היא מחרוזת שגיאת המערכת, הכישלון השקט של awk שנעשה מפורש. ו־`print {$out} ...` זקוק לסוגריים המסולסלים סביב מטפל הקובץ כשהוא משתנה; הצורה החשופה `print FH ...` (ללא פסיק) היא למטפלים בעלי שם, מה שהוא מעידה נפוצה של היום הראשון. ## שורות־קוד־אחת ומתגים שורת־הקוד־האחת היא המגרש הביתי של awk וגם של Perl. משפחת המתגים שמשחזרת את awk: `-e` מספק את התוכנית, `-n` עוטף אותה בלולאה לכל־רשומה (ה־`{ }` המשתמע של awk), `-p` עושה את אותו דבר עם הדפסה אוטומטית בסוף כל מחזור, `-a` מפצל אוטומטית אל `@F` (פיצול השדה האוטומטי של awk), `-F` קובע את תבנית הפיצול (ה־`FS` של awk), ו־`-l` מטפל בסיומות שורה (נוחות ה־`ORS`/`RS` של awk). `BEGIN { }` ו־`END { }` הם **אותן מילות מפתח** כמו awk, הרצות לפני ואחרי הלולאה. ```awk awk '/error/ { print }' log.txt # print error records awk '{ s += $NF } END { print s }' input.txt # sum the last field awk -F, '{ print $1 }' input.txt # first CSV field ``` ```perl perl -ne 'print if /error/' log.txt perl -ane 'END { print "$s\n" } $s += $F[-1]' input.txt perl -F, -ane 'print "$F[0]\n"' input.txt ``` אלה מוצגים ללא פלט מכיוון שמתגי הלולאה המשתמעת אינם מזוהים על ידי build זה של `pperl` עדיין (ראו את ההערה בראש). כל אחד ממופה לצורת לולאה מפורשת מאומתת: `perl -ne 'CODE'` הוא `while (<$fh>) { CODE }`, `-ane` מוסיף `my @F = split` בראש, ובלוקי `BEGIN`/`END` עובדים בסקריפט מלא בדיוק כמו ב־awk. הצורה הניתנת־להרצה ”סכימת עמודה עם BEGIN/END“: ```perl use v5.42; my $n = 0; my $sum = 0; BEGIN { say "start" } # runs before the loop, like awk BEGIN END { say "lines=$n sum=$sum" } # runs after, like awk END open my $fh, '<', '/tmp/scores.txt' or die "open: $!"; while (<$fh>) { my @F = split; $n++; $sum += $F[1]; # awk: sum += $2 } # start # lines=4 sum=300 ``` המלכודת: עד שהמתגים ייכנסו ל־`pperl`, כתבו את הלולאה המפורשת (היא רצה היום וזה ממילא מה שהמתגים מתרחבים אליו), ועיינו ב[מדריך שורות־הקוד־האחת](../oneliner/index.md) לקטלוג המתגים המלא ולעשרות מתכונים - זה הדבר בעל המנוף הגבוה ביותר לקריאה בהגעה מרקע של awk. ל־Perl יש גם תת־שגרות מלאות, הפניות, מודולים, ותכנות מונחה־עצמים אם הסקריפט שלכם גדל מעבר לשורת־קוד־אחת; ראו את [מדריך התכנות מונחה־העצמים](../oop/index.md) ואת שאר מדריכי ההגעה־מ. ## זרימת בקרה מילות הבקרה של awk ממופות אל אלה של Perl כמעט שם־לשם. ה־`next` של awk (דלג לרשומה הבאה) הוא ה־`next` של Perl; `break`/`continue` בלולאות awk הם `last`/`next` של Perl; ה־`for (k in arr)` של awk הופך ל־`for` של Perl על `keys`. הסוגריים המסולסלים ו־`;` זהים; Perl מוסיפה את צורות הסיומת הנקראות כמו תבניות awk. ```awk awk '{ if ($2 < 70) next; print }' input.txt ``` ```perl use v5.42; open my $fh, '<', '/tmp/scores.txt' or die "open: $!"; while (<$fh>) { my @F = split; next if $F[1] < 70; # awk: if ($2 < 70) next print; } # alice 85 90 # carol 95 100 ``` המלכודת: אופרטורי ההשוואה של Perl באים בשתי משפחות ואתם בוחרים לפי *הטיפוס של האופרנדים*, בעוד של־awk יש רק `<`/`==` לשניהם. מספרים משתמשים ב־`==`, `<`, `>`, `<=>`; מחרוזות משתמשות ב־`eq`, `lt`, `gt`, `cmp`. awk מכריעה השוואה מספרית־מול־מחרוזתית לפי הערכים בזמן ריצה; Perl מכריחה אתכם לבחור את האופרטור. שימוש ב־`==` על מחרוזות (או `eq` על מספרים) הוא באג שקט ותכוף - `"abc" == "xyz"` הוא אמת ב־Perl (שניהם הופכים מספרית ל־0), מה שכמעט אף פעם אינו מה שהתכוונתם אליו. ## משתנים ונתונים זה המיפוי המשמח ביותר במדריך: המערך האסוציאטיבי של awk הוא **האש** Perl, והניבים היומיומיים כמעט זהים. ה־`count[$1]++` של awk הוא ה־`$count{$F[0]}++` של Perl; `for (k in count)` הוא `for my $k (keys %count)`; `if (k in count)` הוא `exists $count{$k}`. ההסטה האחת היא הסיגיל - ההאש כולה היא `%count`, אך ערך אחד הוא `$count{$key}`. ```awk awk '{ total[$1] += $2 + $3 } END { for (k in total) print k, total[k] }' input.txt ``` ```perl use v5.42; open my $fh, '<', '/tmp/scores.txt' or die "open: $!"; my %total; while (<$fh>) { my @F = split; $total{$F[0]} += $F[1] + $F[2]; # awk: total[$1] += $2 + $3 } for my $name (sort keys %total) { # awk END loop over the array say "$name $total{$name}"; } # alice 280 # bob 130 # carol 195 ``` הניב הדו־קבצי `NR==FNR` - טען מפתחות מהקובץ הראשון, ואז בדוק חברות בשני - הוא לולאה מפורשת אחת לכל קובץ ב־Perl, מה שברור יותר משורת־הקוד־האחת של awk שהוא מחליף: ```perl use v5.42; my %seen; open my $f1, '<', '/tmp/data.csv' or die "open: $!"; while (<$f1>) { my ($k) = split /,/; # first field only $seen{$k} = 1; } close $f1; open my $f2, '<', '/tmp/scores.txt' or die "open: $!"; while (<$f2>) { my ($k) = split; print if $seen{$k}; # awk: ($1 in seen) } # alice 85 90 # bob 70 60 # carol 95 100 # alice 50 55 ``` המלכודת: להאש אין סדר מובנה (ה־`for (k in arr)` של awk גם הוא לא־מסודר, כך שזה לא יפתיע אתכם), לכן עברו `sort keys %h` כשאתם רוצים סדר יציב. חברות היא `exists $h{$k}`, לא ה־`k in arr` של awk - ועצם *קריאת* `$h{$k}` כדי לבדוק אותו תייצר את המפתח לכדי קיום בהקשרים מסוימים, מה ש־`exists` לעולם אינו עושה. מספרים ומחרוזות מומרים אוטומטית ב־Perl כמו ב־awk, אך זכרו את הפיצול `==` מול `eq` מתוך [זרימת בקרה](). ## מלכודות בהגעה מ־awk המלכודות, מקובצות לסריקה אחרונה לפני שאתם כותבים: - **שדות הם מבוססי־אפס.** ה־`$1` של awk הוא `$F[0]`, `$2` הוא `$F[1]`, והרשומה כולה `$0` היא `$_`. `NF` הוא `scalar @F`; השדה האחרון הוא `$F[-1]`, לא `$F[NF]`. - **`<$fh>` שומר על תו השורה החדשה הנגרר,** בניגוד ל־`$0` של awk. `chomp` כדי לקצץ אותו. - **`substr` הוא מבוסס־אפס,** בעוד שזה של awk מבוסס־אחד: `substr($s,1,3)` של awk הוא `substr($s,0,3)` של Perl. - **`s///` מחזיר ספירה, לא את המחרוזת החדשה.** `my $x = $s =~ s/a/b/` שם את *ספירת* ההחלפות ב־`$x`. העתיקו תחילה, או השתמשו בדגל `/r` כדי לקבל מחרוזת חדשה. - **שתי משפחות השוואה.** מספרים משתמשים ב־`==`/`<`/`<=>`; מחרוזות משתמשות ב־`eq`/`lt`/`cmp`. ה־`==`/`<` היחיד של awk מפוצל לשניים, נבחר לפי אופרטור, לא לפי ערך. `"abc" == "xyz"` הוא אמת (שניהם הופכים מספרית ל־0). - **`split` חשוף הוא מצב ברירת המחדל של awk.** `split` (ללא ארגומנטים) מפצל את `$_` על רווחים לבנים ומקצץ רווחים מובילים. `split / /` (ביטוי רגולרי עם רווח אחד) הוא מילולי ו *אינו* מקצץ - השתמשו ב־`split` פשוט עבור ה־`FS` של ברירת המחדל של awk. - **חברות היא `exists $h{$k}`, לא `k in arr`.** בדיקת מפתח על ידי קריאת `$h{$k}` יכולה לייצר אותו אוטומטית; `exists` לעולם אינו עושה זאת. - **`open` אינו מפסיק בכישלון.** השתמשו ב־`open my $fh, '<', $path or die "...: $!"`. `$!` היא מחרוזת שגיאת המערכת. - **מתגי הלולאה המשתמעת (`-n`/`-p`/`-a`/`-F`/`-i`/`-l`) עדיין אינם מזוהים על ידי build זה של `pperl`.** רק `-e` עובד היום. כתבו את הלולאה המפורשת `while (<$fh>) { my @F = split; ... }`, שהיא בדיוק מה שהמתגים מתרחבים אליו, עד שהם ייכנסו.