Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Parsing a file one line at a time

by cburns (Novice)
on Jul 23, 2000 at 00:25 UTC ( [id://23921]=perlquestion: print w/replies, xml ) Need Help??

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

How do I parse a file one line at a time? I passed the file as an argument to the prog, and I'm trying to place the lines of the file into an array. Here's the code:
#!/usr/local/bin/perl # server.pl, my mini-server in perl open(FILE1, $ARGV[0]); while (<FILE1>) { @lines = $_; } print "lines[0] = $lines[0]\n"; print "lines[1] = $lines[1]\n"; print "lines[2] = $lines[2]\n";
here's the file:
> more test4a.txt POST /cgi-bin/myprog.cgi HTTP/1.0 UserAgent: MyBrowser Referer: http://www.rutgers.edu Content-type: application/x-www-form-urlencoded Content-length: 16
and here's the output:
> ./server.pl test4a.txt lines[0] = Content-length: 16 lines[1] = lines[2] =
Do I need to have '\n' at the end of each line in the file, and then use split on the '\n' ? The program seems to be reading the entire file and placing the last line only into the array.
Thanks

Replies are listed 'Best First'.
RE: Parsing a file one line at a time
by ar0n (Priest) on Jul 23, 2000 at 00:34 UTC
    This is wrong:
    while (<FILE1>) { # this @lines = $_; }

    Perl is expecting a list, and all you do is assign a scalar. You have to use push to append the $_ onto the array:
    while(<FILE1>) { push @lines, $_; }

    or, faster:
    @lines = <FILE1>;


    -- ar0n
RE: Parsing a file one line at a time
by autark (Friar) on Jul 23, 2000 at 00:38 UTC
    Hi!

    Actually you only need to do this:

    open(FILE1, $ARGV[0]) || die "Error: $!\n"; @lines = <FILE1>;
    This evaluated <FILE1> in list-context, and thus the whole file will be put in the @lines-array, one entry per line (or whatever you have assigned to $/)

    So then, why didn't your code work as you expected ? Well - the line

    @lines = $_;
    assigns the variable $_ to the array @lines. You are declaring the contents of @lines each and every time through that loop. It's almost the same with variables:
    $foo = $_;
    this also redeclares the contents of $foo every time it is evaluated. With scalars we usually use the . (dot) operator or string concat. operator to avoid redeclaring its content:
    $foo .= $_;
    or:
    $foo = $foo . $_;
    So, with arrays we have something similar:
    push @lines, $_;
    That will add to @lines instead of redeclaring its contents.

    Autark

      you (probably) might want to use some idomatic perl, its called 'slurp mode'. It means being able to take in (slurp) the whole file in one go, this is possible by temporarily 'undef'ining the File Seperator $\.
      open(FILE1, $ARGV[0]) || die "Error: $!\n"; { local $/; #value is restored at end this block undef $/; #'slurp mode' @lines = <FILE1>; #slurp all lines } #$/ is as back 'to normal', so nothing unexpected happens later
      local is 'sometimes' the 'right' way.
        Actually, "slurp" mode is used for reading the contents of a file into a scalar. You're using an array. If you assign a filehandle to an array, Perl just "understands" and reads the entire file into the array. This code works fine:
        open(FILE1, $ARGV[0]) || die "Error: $!\n"; @lines = <FILE1>;
        Cheers,
        Ovid
Re: Parsing a file one line at a time
by fundflow (Chaplain) on Jul 23, 2000 at 01:29 UTC
    It seems like you don't need to read the whole file in one go. Instead, you can process a line at a time.
    e.g.:
    open(FILE1, $ARGV[0]); $c=0; while (<FILE1>) { $line=$_; printf("line %2d: %s", $c++, $line); $ref=$1 if /^Referer: (.*)/; }
    You can do the same for the other fields.

    HTH
      I'll raise you one and reveal the wonderful $.:
      while (<>) { printf("line %2d: %s", $., $_); $res = $1 if /^Referer: (.*)$/; }
      You can get rid of the open if you want to open the file specified as the first argument. $. keeps track of the current line number. (You ought to check your open call for success, too.)
Re: Parsing a file one line at a time
by cburns (Novice) on Jul 23, 2000 at 03:04 UTC
    Thanks everyone!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://23921]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2024-03-29 13:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found