[grand-rapids-pm-list] Perl Puzzle 6/29/2007

Ed Eddington Ed.Eddington at priorityhealth.com
Fri Jun 29 13:04:56 PDT 2007


For those who didn't make the meeting, we had a nice group discussion on Design Patterns and large-scale development - thanks Jason! Also, below are the results of the Perl Puzzle for your review.

Ed Eddington
---

> Perl Puzzle
>
> Here's a pretty basic problem. We need to add line numbers to each line of a text file. We need to turn this:
>
> This text file
> may have hundreds
> of lines of text
>
> ...into this:
>
> 1 This text file
> 2 may have hundreds
> 3 of lines of text
>
> Write a quick Perl script to accomplish this. Time can be money, so the first correct response will win their choice of book from our Library. Also, creativity counts, so a free book will also go to the person whose script accomplishes this with the fewest bytes of code (don't bother with 'use strict;' here!). Your script should accept a filename as a parameter and modify the file in place. Please email your code to me (not the list) by Thursday 5PM. Good luck!


First correct responses:
Michael Richey
Bill Ott
Jason Porritt
Pete Litwinchuk

The winner "least bytes of code":
Michael Richey with only 12 bytes!

#!/usr/bin/perl -pi
s/^/$. /

Explanation:

First "-p" causes Perl to assume the following loop around your script:

LINE:
while (<>) {
    # script
}
continue {
    print or die "-p destination: $!\n";
}

So, we're looping over the file and the lines are printed automatically.

Next "-i" allows for in place editing.  Files processed by <> are
renamed and the output file is set to the original file name.  It then
sets the default output of print to be that output file (i.e. the
original file name).  So we got our automatic print from the -p and the
automatic output file from -i. Now we just have to add a line number.

The "$." gives us the line number of the file currently being
processed.  I was using a counter before I discovered this.

I've always used s/^/something / to prepend "something" to a line.

Evolution of the script:

Version 1-ish (found out about $. before I was using ++$l):
#!/usr/bin/perl
$f=pop;
open I,$f;
while(<I>){$t.="$. $_"}
open O,">$f";
print O $t;

Version 2 (found out about -i):
#!/usr/bin/perl -i
while(<>){s/^/$. /;print}

Version 3 (found out about -p):
#!/usr/bin/perl -pi
s/^/$. /;

Version 4 (you don't need a semi colon for the last line of a while loop):
#!/usr/bin/perl -pi
s/^/$. /

Thanks,
Michael
------ End of Forwarded Message




SOME OTHER ENTRIES:

-- -- -- -- -- -- -- -- -- -- --

my $sFileName = $ARGV[0];
my $i = 0;
if (open ( LOG, $sFileName)){
    open( OUT, "> Output.txt" );
    while (<LOG>)
    {
        $i++;
        print OUT "$i $_";
    }
    close LOG;
    close OUT;
}
system "del $sFileName";
system "ren Output.txt $sFileName";


-- -- -- -- -- -- -- -- -- -- --

Modify the original, and make a backup:
   perl -i.bak '$i++;s/^/$i\. /' <infile>

Modified file to STDOUT:
   perl -p -e '$i++;s/^/$i\. /' <infile>

Pipe the results to a new file, leaving the original untouched:
   perl -p -e '$i++;s/^/$i\. /' <infile> > <outfile>

-- -- -- -- -- -- -- -- -- -- --

with -n: END{open A,">$ARGV";print A $i}$i.="$. $_"
without: while(<>){$i.="$. $_"}open A,">$ARGV";print A $i

-- -- -- -- -- -- -- -- -- -- --

( this will work, providing you redirect stdin... )

perl  linenos.pl <filename.txt

where linenos.pl =
while (<STDIN>) {print ++$i." ".$_;}

-- -- -- -- -- -- -- -- -- -- --

** ** **  PRIVILEGED AND CONFIDENTIAL  ** ** **
This email transmission contains privileged and confidential information intended only for the use of the individual or entity named above.  Any unauthorized review, use, disclosure or distribution is prohibited and may be a violation of law.  If you are not the intended recipient or a person responsible for delivering this message to an intended recipient, please delete the email and immediately notify the sender via the email return address or mailto:postmaster at priorityhealth.com.  Thank you.

- end -



More information about the grand-rapids-pm-list mailing list