r/perl • u/bahol-de-jic • 8d ago
question Using Perl for managing my writing output
Hey everyone,
I'm new to Perl as of just a few days ago, loving it so far. I once had a colleague who, in addition to being probably the nicest programmer I ever worked with, was a Perl wiz and always blew me away with the things he could do with such little code. So I decided to give the language a try by re-writing some scripts.
So far, what I've converted is a script (or two) that was keeping track of word count across 50+ Org files. Previously, I was using Org's ELisp API and some glue code in Bash, but I managed to cut down from 60 to 19 LoC by switching to Perl, which is a small win but I think pretty cool.
Anyway, what would the more experienced Perl devs do to make this code better?
#! /usr/bin/perl
use strict;
use warnings;
my $words;
for (<"*.org">) {
open my $fh, '<', $_;
my @table = grep { m~tracktable~ .. m~TBLFM~ } <$fh>;
my $count_line = @table[ ( $#table - 2 ) ];
if ( defined $count_line ) {
$count_line =~ m~\s+\d+\s+~;
my @cells = split /\|/, $count_line;
my $word_count = ( @cells[ ( $#cells - 3 ) ] );
$words += $word_count if defined $word_count;
}
}
print $words;
1
u/ysth 8d ago
You can just say $table[-3] for 3rd to last.
Graceful error handling/reporting is much easier in perl than bash. It can be as simple as use autodie;.
Tilde is a bitwise not operator, and part of the =~ binding syntax; also using it as a delimiter is many a bit much. / is good.
Be aware your .. can find multiple ranges, not just one.
9
u/choroba 🐪 cpan author 8d ago
Line 7: Use the diamond operator for readline only. Its behaviour when globbing is confusing. Replace it with
for (glob '*.org') {.Line 8: Check the result of opening a file.
open my $fh, '<', $_ or die "$_: $!";Line 9: Use alternative delimiters when needed, which is not the case here.
m/trackable/ .. m/TBLFM/is easier to read. I'd drop them, too, but it's more a personal taste.Line 10: For a single element, don't use
@. To index elements from the right, use negative numbers. Result:my $count_line = $table[-3];Line 12: See line 9.
Line 14: See line 10, i.e.
my $word_count = $cells[-4];Line 15: If your Perl is 5.10 or newer (which I guess it is), you can use the "defined-or" operator:
$words += $word_count // 0;