Can anyone explain this code?

P

PerlNovice

I would really appreciate it if someone could explain this code?

perl -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

I understand parts of it but not all. I can't find help on what the -ne
stands for. Any pointers to where I can go on the internet to find
meaning of this would be appreciated.
 
U

usenet

PerlNovice said:
I understand parts of it but not all. I can't find help on what the -ne
stands for. Any pointers to where I can go on the internet to find
meaning of this would be appreciated.

You don't need the internet:

perldoc perlrun
 
U

usenet

PerlNovice said:
This just gives me explanation of perl -ne
and nothing else.

Well, that's the only thing that you specifically asked about.

You indicated that you already understood other parts of it, so it
doesn't seem necessary to walk through the code and explain it
statement-by-statement. Since I'm not a mind-reader (like Tad), I
don't know which other statements are causing you confusion.

Of course, looking at the code all crammed together like that is bound
to add to anyone's confusion (except maybe Abigail). You might want to
run it through perltidy before trying to mentally parse it:

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)};
}

Ah, that's better. That makes it easier to parse and easier to ask for
clarification about some particular aspect of the code.
 
P

PerlNovice

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.
-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
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 $!"
2)if @F=/(\d+)\s+(\w+)\s+(\d+)\s+(\d\d):(\d\d):(\d\d).*MATCHED/
3)$m{$2}=$1 if /(\d+)\s+(?=(.))(MATCHED|DUPLICATE|RESIDUAL)/
4)@m{qw(M D R)}}

I would appreciate any explanations and any comments from anyone.
Thanks.
 
P

PerlNovice

One more thing. I want to put this in a file called MyProc.sh and
execute like this:

perl -ne MyProc.sh

What do I need to do that?

Thanks.
 
J

Joe Smith

PerlNovice said:
1),">".(join"_",@F).".log" or die "@F $!"
2)if @F=/(\d+)\s+(\w+)\s+(\d+)\s+(\d\d):(\d\d):(\d\d).*MATCHED/

The following is not an exact translation,
but should help you understand.

# Expecting input like "1 Sept 2006 01:23:45 some text MATCHED"
@F=/(\d+)\s+(\w+)\s+(\d+)\s+(\d\d):(\d\d):(\d\d).*MATCHED/;
if (@F) {
$filename = "$F[0]_$F[1]_$F[2]_$F[3]_$F[4]_$F[6].log";
open F,'>',$filename or die "$filename $!";
}
3)$m{$2}=$1 if /(\d+)\s+(?=(.))(MATCHED|DUPLICATE|RESIDUAL)/

$m{M} = $1 if /(\d+)\s+MATCHED/;
$m{D} = $1 if /(\d+)\s+DUPLICATE/;
$m{R} = $1 if /(\d+)\s+RESIDUAL/;
4)@m{qw(M D R)}}

printf ".....",$m{M},$m{D},$m{R};

-Joe
 
P

Peter J. Holzer

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
 
P

PerlNovice

Michele/David, I put David's tidied up version in a file called
MyProc.pl. I then tried
to execute it and see if it produces the same resul as follows:

perl -ne MyProc.pl

Nothing happens. It doesn't even come back to command prompt.

Joe, thank you for your response. However, I would need little bit more
detail to understand.

1),">".(join"_",@F).".log" or die "@F $!"
I know the part after the comma is the second part of the file handle.
But what does
">".(join"_",@F).".log" mean? I know the file being created is a .log
file. What is
">".(join"_",@F).? I know @F is the file name that is created later.
How is the file name
created in this format? What d,s,w etc mean? What .*MATCHED? I know
that giving a character
by character explanation will take you long time but any explanation in
this format will be
very helpful. In the meantime, I am trying by best to understand the
code.

A lot of thanks to anyone who responds.
 
T

Tad McClellan

PerlNovice said:
perl -ne MyProc.pl

Nothing happens.


The -n switch makes a while-diamond loop.

Since you did not call the program with any command line arguments
the diamond operator will (attempt to) read from STDIN.

It doesn't even come back to command prompt.


Because it is waiting for you to type some data on STDIN...

But what does
">".(join"_",@F).".log" mean?


perldoc -f join

The concatentation operator is described in:

perldoc perlop

What d,s,w etc mean?


That depends on where d,s,w etc appear in the code.

Those characters do not appear in any code that you've quoted,
so I dunno what they do...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,905
Latest member
Kristy_Poole

Latest Threads

Top