Thank you David, Chris and Michele for your responses. This is what I
understand and this is what I don't understand.
Please correct me if I am wrong:
-n : Loop around the code after the space for as many file names as has
been provided. In my example, just 1.
No it loops around every *line* in the files.
-e: This is telling the compiler that a one line script is being
entered at the command line.
': Beginning of the code to be executed
Actually, the single quotes are to prevent the shell from messing with
the script. The shell will take everything within the single quotes
unaltered and pass it as a single argument to perl.
open F,: Open a file with file handle F followed by separator between 2
arguments of filename
Of the rest, I only understand bits. for example,
@F: An arrary named F. This is defined later.
printf F "MATCHED DUPLICATE RESIDUAL\n%-7d %-9d %-7d\n": Printing a
line to the newly created file sandwiched between 2 newline characters
; : I know they are end of line characters
or die: If the file is not found then send a file not found message to
stdout
Here are the pieces I don't understand:
1),">".(join"_",@F).".log" or die "@F $!"
That's not one piece, that's two pieces. Everything before the "or"
belongs to the open before it. Since it's a bit useless to talk about
pieces of code which were cut apart at random places, I've sent the
complete script through Deparse:
perl -MO=Deparse -ne 'open F,">".(join"_",@F).".log" or die "@F $!" if @F=/(\d+)\s+(\w+)\s+(\d+)\s+(\d\d)
\d\d)
\d\d).*MATCHED/; $m{$2}=$1 if /(\d+)\s+(?=(.))(MATCHED|DUPLICATE|RESIDUAL)/; END{printf F "MATCHED DUPLICATE RESIDUAL\n%-7d %-9d %-7d\n",@m{qw(M D R)}}' INPUTFILE
results in:
LINE: while (defined($_ = <ARGV>)) {
open F, '>' . join('_', @F) . '.log' or die "@F $!" if @F = /(\d+)\s+(\w+)\s+(\d+)\s+(\d\d)
\d\d)
\d\d).*MATCHED/;
$m{$2} = $1 if /(\d+)\s+(?=(.))(MATCHED|DUPLICATE|RESIDUAL)/;
sub END {
printf F "MATCHED DUPLICATE RESIDUAL\n%-7d %-9d %-7d\n", @m{'M', 'D', 'R'};
}
;
}
Now let's move the END block to the end where it belongs:
LINE: while (defined($_ = <ARGV>)) {
open F, '>' . join('_', @F) . '.log' or die "@F $!" if @F = /(\d+)\s+(\w+)\s+(\d+)\s+(\d\d)
\d\d)
\d\d).*MATCHED/;
$m{$2} = $1 if /(\d+)\s+(?=(.))(MATCHED|DUPLICATE|RESIDUAL)/;
}
printf F "MATCHED DUPLICATE RESIDUAL\n%-7d %-9d %-7d\n", @m{'M', 'D', 'R'};
and rearrange the if statements in the loop:
LINE: while (defined($_ = <ARGV>)) {
if (@F = /(\d+)\s+(\w+)\s+(\d+)\s+(\d\d)
\d\d)
\d\d).*MATCHED/) {
open F, '>' . join('_', @F) . '.log'
or die "@F $!"
}
if (/(\d+)\s+(?=(.))(MATCHED|DUPLICATE|RESIDUAL)/) {
$m{$2} = $1
}
}
printf F "MATCHED DUPLICATE RESIDUAL\n%-7d %-9d %-7d\n", @m{'M', 'D', 'R'};
Is it clearer now? You may have to read
perldoc perlsyn
perldoc perlvar
perldoc perlre
perldoc -f open
perldoc perldata
to understand what's going on.
(and to to really understand what it's supposed to do you also need to
know what the file that is read looks like).
BTW, while perl golf and obfuscations are lots of fun and educational,
I don't think it gains you much if you don't even understand basic perl
constructs yet. Start with perl code that's written to be readable, not
as short as possible.
hp