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

I have a text file that has a structure like this:
A=[1, 2, 3, 4 ]

I am trying to parse the file until that last "]". I know a long way of doing this, but I want to know why this doesn't work

open(FIL, $file) || die "can't open file $^E\n"; while(chomp($_ = <FIL>) ne "]"){ #do stuff }

Apparently, the While loop is never terminated, and reads past the end of the file. Any ideas?

Replies are listed 'Best First'.
Re: Parsing Test File
by VSarkiss (Monsignor) on Jan 15, 2002 at 21:05 UTC

    You're not testing for end-of-file, which is indicated by an undef return from the diamond operator. Breaking up your logic to test for EOF will guarantee that it'll stop, even if the file doesn't contain the string you expect. Plus it'll be easier to understand:

    while (<FIL>) { chomp; last if $_ eq ']'; # It's also possible to do "last if /^\]$/", but # all you need is a simple string compare. # do stuff }
    HTH

Re: Parsing Test File
by davis (Vicar) on Jan 15, 2002 at 20:57 UTC
    Chomp returns the number of characters removed, not the actual characters removed.
    Chomp will also only remove the $/ , or input record seperator variable.
    Replacing the chomp with chop might do as you expect.
    See perlvar and perlfunc for more information
    Hope this helps
    davis

    Update The reply by Vsarkiss makes more sense.

      Just for completeness' sake, I'd like to mention one should always prefer chomp over chop for stripping end-of-line characters. The most obvious example of why is if the last line in the file has no trailing newline. In that case chop will break - it will eat a character from your payload. chomp will still do the right thing (which is nothing, in this case).

      Unless you really want to remove the last character of every line, regardless of what that may be, you shouldn't chop.

      thank you. That makes perfect sense.
Re: Parsing Test File
by broquaint (Abbot) on Jan 15, 2002 at 21:07 UTC
    There are several more suitable solutions for parsing the provided example
    my($data) = $input =~ /\[([^\]]+)\]/s;
    or if you want to be really thorough you could try the Text::Balanced module by Damian Conway. Also you probably want to use $! instead of $^E as it's more portable and pretty much the excepted standard.
    HTH

    broquaint

Re: Parsing Test File
by talexb (Chancellor) on Jan 15, 2002 at 21:25 UTC
    In addition to the various ways already mentioned, you could also undef $/; and then (Camel, 3rd edition, p.666) read the file into a single scalar, replacing new lines with spaces. Then you could parse on strings bounded by pairs of [].

    TMTOWTDI. :)

    --t. alex

    "Of course, you realize that this means war." -- Bugs Bunny.