Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I am trying to add a blank row above all lines starting with 10.

Example Source Data:
10record
record
record
10record
etc...

Required Output:

10record
record
record

10record
etc...

My following code is not picking up lines that don't contain 10:

#!usr/bin/perl -w use strict; use warnings; open (DATA, "test.txt") || die "Unable to open file: $!"; open (OUT, ">testout.txt") || die "Cannot create out file: $!"; my $line = <DATA>; my $type = substr ($line,0,2); # match first two characters in each li +ne NEWLINE: while (<DATA>) { chomp; # remove terminating newline if ($type eq "10") { # matches all record 10 print OUT "\n"; print OUT "$line\n"; last if ($type ne "10"); } # loop adds blank row above record 10 elsif ($type ne "10") { # matches all non record 10 print OUT "$line\n"; last if ($type eq "10"); } next NEWLINE; # process next line } # end while close (DATA) || die "Unable to close file: $!"; close (OUT) || die "Unable to close file: $!";

Not sure what I have done wrong in exiting each loop.

Thanks in advance.

Replies are listed 'Best First'.
Re: exiting loops
by davido (Cardinal) on Oct 27, 2004 at 22:58 UTC

    Your two calls to last are meaningless since they appear at the end of their individual blocks; there's nothing else that would have been executed anyway. What I mean is that last is exiting the if conditional block, not the outter loop. There isn't any code to be executed after the if conditionals, aside from the next. Similarly your next NEWLINE is also meaningless since it is the last line of the while block. ...and the while block is named NEWLINE. Meaningless, because you're at the end of the block anyway, there's nothing more for Perl to do besides loop again, even without the 'next' call. You might derive some benefit from looking at perlsyn, where control flow is discussed.

    If I wanted to print a newline before every line that begins with '10', I would do it this way:

    perl -pi.bak -e "m/^10/ and $_ = $/ . $_;" filename.txt

    That you can disect after reading perlrun (to gain an understanding of one-liners), perlop (to look into logical short circuit operators), and perlvar (to see that $/ defaults to the newline character). Hope this is helpful.


    Dave

Re: exiting loops
by TheEnigma (Pilgrim) on Oct 27, 2004 at 23:12 UTC
    You have three problems that I can see.

    You're only putting the contents of a line into $type once, before the loop. Get rid of the my $line and the my $type at the very beginning.

    You don't appear to understand the purpose of last. It will exit your while loop, not the if, so you only go through the loop once. You don't need the two instances of last at all.

    Doing while (<DATA>) as you do, each line will be in $_, which you can then check easily with a regex like this:

    if(/^10/){ print OUT "\n"; }

    or even shorter:

    print OUT "\n" if /^10/;

    Then you do the line:

    print OUT "$_\n";

    just once, for both cases. Remember the line is in $_

    So now your while loop looks like this:

    while(<DATA>){ chomp; print OUT "\n" if /^10/; print OUT "$_\n"; }

    TheEnigma

Re: exiting loops
by TedPride (Priest) on Oct 28, 2004 at 02:35 UTC
    open (DATA, "test.txt") || die "Unable to open file: $!"; open (OUT, ">testout.txt") || die "Cannot create out file: $!"; while (<DATA>) { print OUT "\n" if /^10/; print OUT; } close (DATA) || die "Unable to close file: $!"; close (OUT) || die "Unable to close file: $!";