חד־שורתיים מספריים ושל תאריכים#
pperl כמחשבון, כלי סטטיסטיקה, ומנוע חישובי תאריכים. פרק זה אוסף את המתכונים ההופכים עמודות מספריות, חותמות זמן וכתובות IP לפלט שימושי ללא קובץ סקריפט.
הבסיס המונח הוא קורא שקרא את switches ואת progression. הניבים -lane / -MList::Util=... המשמשים למטה הוצגו שם.
היכן שפרק זה פונה לביצועים: רדוקציות מספריות גדולות הן אחד המקרים שבהם ה־JIT של pperl מצדיק את עלותו. צבירה של for (1 .. 100_000_000) { $s += $_ } רצה כקוד מכונה מהודר לאחר שהפרשן מתחמם. אתם לא נכנסים לזה במפורש - זה נדלק אוטומטית על לולאות מספריות עתירות־חשבון.
חד־שורתיים של חשבון פשוט#
pperl -E 'say 2 ** 64' # 1.84467440737096e+19
pperl -E 'say 2 ** 64 - 1' # rounds (float)
pperl -MMath::BigInt -E 'say Math::BigInt->new(2)->bpow(64)'
# 18446744073709551616
pperl -E 'say 7 / 3' # 2.33333333333333
pperl -E 'say int(7 / 3)' # 2
pperl -E 'say 7 % 3' # 1
pperl -E 'say sqrt(2)' # 1.4142135623731
pperl -E 'say atan2(1, 1) * 4' # 3.14159265358979 (pi)
sprintf שולט ברוחב ובדיוק הפלט:
pperl -E 'printf "%.4f\n", 22/7' # 3.1429
pperl -E 'printf "%10.2f\n", 42.5' # 42.50
pperl -E 'printf "%08d\n", 42' # 00000042
pperl -E 'printf "%x %o %b\n", 255, 255, 255' # ff 377 11111111
סכומים, מינימה, מקסימה, ממוצעים#
List::Util מגיע עם Perl 5 - אין צורך בהתקנה.
לכל שורה#
pperl -MList::Util=sum -lane 'print sum @F' data.txt
pperl -MList::Util=min -lane 'print min @F' data.txt
pperl -MList::Util=max -lane 'print max @F' data.txt
# Per-line mean
pperl -MList::Util=sum -lane 'print sum(@F) / @F' data.txt
על פני כל השורות#
# Total sum
pperl -MList::Util=sum -lane '$s += sum @F; END { print $s }' data.txt
# Running min / max using // (defined-or)
pperl -MList::Util=min -alne '$m = min($m // (), @F); END { print $m }' data.txt
pperl -MList::Util=max -alne '$m = max($m // (), @F); END { print $m }' data.txt
# Mean of one column (third), ignoring blank lines
pperl -lane 'next unless /\S/; $s += $F[2]; $n++;
END { printf "%.4f\n", $s / $n }' data.txt
$m // () מחזיר רשימה ריקה כש־$m הוא לא־מוגדר, כך שהאיטרציה הראשונה אינה מזהמת את min/max ב־undef. ראו perlop ל־//.
סכימת עמודה יחידה#
# Sum of column 3 (zero-indexed: $F[2])
pperl -lane '$s += $F[2]; END { print $s }' data.txt
# Negative or zero entries only
pperl -lane '$s += $F[2] if $F[2] <= 0; END { print $s }' data.txt
סטיית תקן#
pperl -lane '
$n++; $s += $_; $s2 += $_**2 for @F;
END {
my $n2 = $n * @F; # total count (assumes rectangular data)
my $mean = $s / $n2;
printf "mean=%.4f sd=%.4f\n",
$mean, sqrt($s2 / $n2 - $mean ** 2);
}
' data.txt
לכל דבר מעבר לממוצע+סטיית־תקן, פנו ל־Statistics::Descriptive:
pperl -MStatistics::Descriptive -lane '
BEGIN { our $stat = Statistics::Descriptive::Full->new }
$stat->add_data(@F);
END { printf "median=%.2f mean=%.2f sd=%.2f\n",
$stat->median, $stat->mean, $stat->standard_deviation }
' data.txt
מספרים אקראיים ודגימה#
# 10 random integers in [5, 15)
pperl -E 'say join ",", map { int(rand(10)) + 5 } 1 .. 10'
# 8-character random lowercase password
pperl -E 'say join "", map { ("a".."z")[rand 26] } 1 .. 8'
# 8-character random alphanumeric
pperl -E 'say join "", map { ("a".."z", 0..9)[rand 36] } 1 .. 8'
# Random UUID (using Data::UUID)
pperl -MData::UUID -E 'say Data::UUID->new->create_str'
# Shuffle the fields of each line
pperl -MList::Util=shuffle -alne 'print join " ", shuffle @F' data.txt
# Pick one random line from a file (reservoir sample, size 1)
pperl -ne 'rand($.) < 1 && ($pick = $_); END { print $pick }' file.txt
תכסיס המאגר הוא התשובה הנכונה כשהקובץ גדול מדי ל־slurp או שמספר השורות שלו אינו ידוע - לכל שורה יש הסתברות שווה להיות המודפסת, במעבר אחד בדיוק.
עצרות, GCD, LCM, ראשוניים#
# Factorial
pperl -E '$f = 1; $f *= $_ for 1 .. 20; say $f'
pperl -MMath::BigInt -E 'say Math::BigInt->new(100)->bfac'
# GCD / LCM (built into Math::BigInt under bgcd / blcm)
pperl -MMath::BigInt=bgcd -anle 'print bgcd(@F)' nums.txt
pperl -MMath::BigInt=blcm -anle 'print blcm(@F)' nums.txt
# Euclid's algorithm for two numbers
pperl -le '$n=20; $m=35; ($m,$n) = ($n, $m % $n) while $n; print $m'
ראשוניות:
# Regex-based primality test (Abigail). Input: one integer per line.
pperl -lne '(1 x $_) !~ /^1?$|^(11+?)\1+$/ && print "$_ prime"' nums.txt
# Reliable for large numbers: use Math::Prime::Util
pperl -MMath::Prime::Util=is_prime -lne '
print "$_ prime" if is_prime($_)
' nums.txt
תכסיס ה־regex הוא סקרנות; Math::Prime::Util הוא התשובה הרצינית.
IP ↔ מספר שלם#
# Dotted-quad → 32-bit integer
pperl -MSocket -le 'print unpack "N", inet_aton "127.0.0.1"'
# 2130706433
# Integer → dotted-quad
pperl -MSocket -le 'print inet_ntoa pack "N", 2130706433'
# 127.0.0.1
unpack "N" קורא ארבעה בתים כמספר שלם לא־מסומן 32־ביט big-endian. ה־pack "N" המקביל כותב אחד.
תאריך ושעה#
היום, עכשיו, epoch#
pperl -E 'say time' # epoch seconds
pperl -E 'say scalar localtime' # Mon Apr 22 14:31:07 2026
pperl -E 'say scalar gmtime' # same, UTC
pperl -MPOSIX=strftime -E 'say strftime "%F %T", localtime'
# 2026-04-22 14:31:07
strftime הוא הדרך הנקיה לעצב; localtime בהקשר רשימה מחזיר (sec, min, hour, mday, mon, year, wday, yday, isdst).
חשבון תאריכים#
POSIX::mktime מנרמל שדות מחוץ לטווח (חודש 13 הופך לחודש 1 של השנה הבאה, יום 32 הופך ליום 1 של החודש הבא, וכו«), ולכן חשבון תאריכים משמעו ״הפחתת N משדה, mktime, strftime״.
# Yesterday's date
pperl -MPOSIX=strftime -MPOSIX=mktime -E '
my @t = localtime;
$t[3] -= 1;
say strftime "%F", localtime mktime @t
'
# 30 days ago
pperl -MPOSIX=strftime -MPOSIX=mktime -E '
my @t = localtime;
$t[3] -= 30;
say strftime "%F", localtime mktime @t
'
# First Monday of next month
pperl -MPOSIX=strftime -MPOSIX=mktime -E '
my @t = localtime;
$t[3] = 1; $t[4]++; # first of next month
my $epoch = mktime @t;
my @nm = localtime $epoch;
$epoch += ((8 - $nm[6]) % 7 || 7) * 86400 if $nm[6] != 1;
# ^ if not already Monday, advance to next Monday
say strftime "%F", localtime $epoch
'
לכל דבר מורכב יותר (אזורי זמן, חישובי ימי עסקים, שבועות ISO), פנו ל־DateTime:
pperl -MDateTime -E '
my $d = DateTime->now->subtract(days => 30);
say $d->strftime("%F %T %Z")
'
חותמות זמן ב־logs#
# Sum the durations (last field, milliseconds) of lines matching "slow"
pperl -lane '$s += $F[-1] if /slow/; END { print $s, " ms total" }' app.log
# Count events per hour (assumes ISO timestamp first field)
pperl -lane '
(my $hour = $F[0]) =~ s/:\d{2}:\d{2}.*//;
$h{$hour}++;
END { print "$_ $h{$_}" for sort keys %h }
' events.log
CSV ו־TSV#
TSV with no embedded tabs: -F'\t' is fine. Real CSV needs Text::CSV:
# Sum the third column of a properly quoted CSV
pperl -MText::CSV -E '
my $csv = Text::CSV->new({ binary => 1 });
my $total = 0;
while (my $row = $csv->getline(*STDIN)) {
$total += $row->[2];
}
say $total
' < data.csv
# Re-emit a CSV with only selected columns
pperl -MText::CSV -E '
my $csv = Text::CSV->new({ binary => 1, eol => "\n" });
while (my $row = $csv->getline(*STDIN)) {
$csv->print(*STDOUT, [ @{$row}[0, 2, 4] ]);
}
' < data.csv > trimmed.csv
האופציה binary => 1 שומרת על בתים שלמים; האופציה eol => "\n" גורמת ל־print להוסיף שורות חדשות.
JSON#
JSON::PP מגיע עם Perl; Cpanel::JSON::XS מהיר יותר אם הוא מותקן.
# Extract the "name" field from each line of NDJSON
pperl -MJSON::PP -lne '
my $o = JSON::PP->new->decode($_);
print $o->{name};
' events.ndjson
# Convert each line of TSV to JSON
pperl -MJSON::PP -F'\t' -lane '
print JSON::PP->new->encode({ id => $F[0], name => $F[1] })
' data.tsv
# Pretty-print a single JSON document
pperl -MJSON::PP -0777 -ne '
print JSON::PP->new->pretty->encode(JSON::PP->new->decode($_))
' small.json
ל־JSON גדול, פרסרים זורמים (JSON::Streaming::Reader) עדיפים על slurping; קבצי מסמך־יחיד מתחת לכמה מאות מגה־בייט בסדר עם הנ״ל.
Base64, קידוד URL, hex#
# Base64 encode/decode (of a whole file)
pperl -MMIME::Base64 -0777 -ne 'print encode_base64($_)' file
pperl -MMIME::Base64 -0777 -ne 'print decode_base64($_)' file.b64
# URL encode/decode
pperl -MURI::Escape -lne 'print uri_escape($_)' < urls.txt
pperl -MURI::Escape -lne 'print uri_unescape($_)' < encoded.txt
# Hex ↔ integer
pperl -E 'printf "%x\n", 255' # ff
pperl -E 'say hex "ff"' # 255
# Hex dump of a file (like xxd -p)
pperl -0777 -ne 'print unpack "H*", $_' file.bin
# Reverse: hex dump → bytes
pperl -0777 -ne 'chomp; print pack "H*", $_' file.hex > file.bin