How does one move down a line in a file?

Discussion in 'Perl Misc' started by John, Oct 14, 2003.

  1. John

    John Guest

    I'd like to move down a file and assign each line to a different variable.
    How can I skip/move forward a line within the following while loop?

    while (<FILE>) {
    first = $_;
    second = $_;
    third = $_;
    }

    # all below vars have different values
    print $first;
    print $second;
    print $third;


    Thanks
    John, Oct 14, 2003
    #1
    1. Advertising

  2. John

    Anno Siegel Guest

    John <> wrote in comp.lang.perl.misc:
    > I'd like to move down a file and assign each line to a different variable.


    I'm pretty sure you don't really want to do that. How would you access the
    last line of a file of 1234 lines? $one_thousand_two_hundred_thirty_fourth?

    You *may* want to assign the lines to an array with each line in one
    position.

    > How can I skip/move forward a line within the following while loop?
    >
    > while (<FILE>) {
    > first = $_;
    > second = $_;
    > third = $_;
    > }


    First off, you forgot the "$"s in front of your variables. A quick test
    (perl -c) would have shown your error. If you post code, please make
    sure it is syntactically correct.

    Otherwise, the code doesn't do in the least what you want. It assigns
    the *same* line (in $_) into $first, $second and $third. Then, in the
    next iteration, it overwrites the values with the next line. You end
    up with the last line of the file in all three variables.

    With an array the solution looks like this:

    my @list;
    while (<FILE>) {
    push @list, $_;
    }

    or just

    my @list = <FILE>;

    > # all below vars have different values
    > print $first;
    > print $second;
    > print $third;


    print $list[ $_] for 0 .. 2;

    Anno
    Anno Siegel, Oct 14, 2003
    #2
    1. Advertising

  3. John

    Anno Siegel Guest

    Abigail <> wrote in comp.lang.perl.misc:
    > John () wrote on MMMDCXCVI September MCMXCIII in
    > <URL:news:NpRib.150645$>:
    > ~~ I'd like to move down a file and assign each line to a different variable.
    > ~~ How can I skip/move forward a line within the following while loop?
    > ~~
    > ~~ while (<FILE>) {
    > ~~ first = $_;
    > ~~ second = $_;
    > ~~ third = $_;
    > ~~ }
    >
    > It depend a bit on what you want to do with the last lines if the
    > file doesn't have a multiple of three lines in the file, but I
    > would do something like:
    >
    > { my $first = <FILE> err last;
    > my $second = <FILE> err last;
    > my $third = <FILE> err last;
    >
    > # Process lines here.
    >
    > redo;
    > }


    Ah... you probably understood the OPs intention better than I did
    in another reply.

    The "err" operator looks interesting. How is it specified?

    Anno
    Anno Siegel, Oct 14, 2003
    #3
  4. John

    John Guest

    "Anno Siegel" <-berlin.de> wrote in message
    news:bmgpm4$foe$-Berlin.DE...
    > John <> wrote in comp.lang.perl.misc:
    > > I'd like to move down a file and assign each line to a different

    variable.
    >
    > I'm pretty sure you don't really want to do that. How would you access

    the
    > last line of a file of 1234 lines?

    $one_thousand_two_hundred_thirty_fourth?
    >
    > You *may* want to assign the lines to an array with each line in one
    > position.
    >
    > > How can I skip/move forward a line within the following while loop?
    > >
    > > while (<FILE>) {
    > > first = $_;
    > > second = $_;
    > > third = $_;
    > > }

    >
    > First off, you forgot the "$"s in front of your variables. A quick test
    > (perl -c) would have shown your error. If you post code, please make
    > sure it is syntactically correct.
    >
    > Otherwise, the code doesn't do in the least what you want. It assigns
    > the *same* line (in $_) into $first, $second and $third. Then, in the
    > next iteration, it overwrites the values with the next line. You end
    > up with the last line of the file in all three variables.
    >
    > With an array the solution looks like this:
    >
    > my @list;
    > while (<FILE>) {
    > push @list, $_;
    > }
    >
    > or just
    >
    > my @list = <FILE>;
    >
    > > # all below vars have different values
    > > print $first;
    > > print $second;
    > > print $third;

    >
    > print $list[ $_] for 0 .. 2;
    >
    > Anno


    Thanks Anno. I actually changed to an array solution and it works as I
    needed it in a much neater way:
    open(FILE, $file);
    @lines = <FILE>;
    close(FILE);
    John, Oct 14, 2003
    #4
  5. John <> wrote:

    > How can I skip/move forward a line within the following while loop?



    By simply reading from the file:


    > while (<FILE>) {
    > first = $_;
    > second = $_;
    > third = $_;


    if ( want_to_skip_line() ) {
    <FILE>; # read and discard line
    }


    > }



    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Oct 14, 2003
    #5
  6. John

    Helgi Briem Guest

    On Tue, 14 Oct 2003 11:50:05 GMT, "John" <> wrote:

    >I'd like to move down a file and assign each line to a different variable.
    >How can I skip/move forward a line within the following while loop?
    >
    >while (<FILE>) {
    > first = $_;
    > second = $_;
    > third = $_;
    >}
    >
    ># all below vars have different values
    >print $first;
    >print $second;
    >print $third;


    Don't do that. Use a hash instead:

    #!perl
    use warnings;
    use strict;
    my %line;
    while (<DATA>)
    {
    $line{$.}= $_;
    }

    # Have a look at the contents of %line
    for (sort { $a <=> $b } keys %line)
    {
    print "$_\t$line{$_}";
    }
    Helgi Briem, Oct 14, 2003
    #6
  7. John <> wrote:


    [ snip full-quote. Please do not do that. ]


    > open(FILE, $file);



    You should always, yes *always*, check the return value from open():

    open(FILE, $file) or die "could not open '$file' $!";


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Oct 14, 2003
    #7
  8. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    Helgi Briem <> wrote in
    news::

    > Don't do that. Use a hash instead:
    >
    > #!perl
    > use warnings;
    > use strict;
    > my %line;
    > while (<DATA>)
    > {
    > $line{$.}= $_;
    > }
    >
    > # Have a look at the contents of %line
    > for (sort { $a <=> $b } keys %line)
    > {
    > print "$_\t$line{$_}";
    > }


    You would do the above instead of

    @line = <DATA>;

    for ($i=0; $i<@line; $i++)
    {
    print "$i\t$line[$i]";
    }

    ?

    - --
    Eric
    $_ = reverse sort $ /. r , qw p ekca lre uJ reh
    ts p , map $ _. $ " , qw e p h tona e and print

    -----BEGIN PGP SIGNATURE-----
    Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

    iQA/AwUBP4v/jmPeouIeTNHoEQLQ4wCeNNGVhWyUvgPgSo2U6yhiYTogMo4An35P
    4SOlnDyTHapWOcgjYeO+5wdD
    =Tpwh
    -----END PGP SIGNATURE-----
    Eric J. Roode, Oct 14, 2003
    #8
  9. John

    Anno Siegel Guest

    Abigail <> wrote in comp.lang.perl.misc:
    > Anno Siegel (-berlin.de) wrote on MMMDCXCVI
    > September MCMXCIII in <URL:news:bmgq1q$foe$-Berlin.DE>:
    > "" Abigail <> wrote in comp.lang.perl.misc:


    [...]

    > "" > would do something like:
    > "" >
    > "" > { my $first = <FILE> err last;
    > "" > my $second = <FILE> err last;
    > "" > my $third = <FILE> err last;
    > "" >
    > "" > # Process lines here.
    > "" >
    > "" > redo;
    > "" > }
    > ""
    > "" Ah... you probably understood the OPs intention better than I did
    > "" in another reply.
    > ""
    > "" The "err" operator looks interesting. How is it specified?
    >
    > The same as the perl6 operator. Avaiable as a patch against 5.8.1 on
    > CPAN: authors/id/H/HM/HMBRAND/dor-5.8.1.diff.


    Ah, very nice. Compiling...

    Anno
    --
    $_ = 'Just a LISP hacker,';
    $x = \ substr( $_, 6, 5);
    $$x = 'nother Perl';
    print
    Anno Siegel, Oct 14, 2003
    #9
  10. John

    Anno Siegel Guest

    Eric J. Roode <> wrote in comp.lang.perl.misc:
    > -----BEGIN PGP SIGNED MESSAGE-----
    > Hash: SHA1
    >
    > Helgi Briem <> wrote in
    > news::
    >
    > > Don't do that. Use a hash instead:
    > >
    > > #!perl
    > > use warnings;
    > > use strict;
    > > my %line;
    > > while (<DATA>)
    > > {
    > > $line{$.}= $_;
    > > }
    > >
    > > # Have a look at the contents of %line
    > > for (sort { $a <=> $b } keys %line)
    > > {
    > > print "$_\t$line{$_}";
    > > }

    >
    > You would do the above instead of
    >
    > @line = <DATA>;
    >
    > for ($i=0; $i<@line; $i++)
    > {
    > print "$i\t$line[$i]";
    > }


    Why that instead of

    print "$_\t$line[$_]" for 0 .. $#line;

    :)

    Anno
    Anno Siegel, Oct 14, 2003
    #10
  11. On Tue, 14 Oct 2003 11:50:05 GMT
    "John" <> wrote:
    > I'd like to move down a file and assign each line to a different
    > variable. How can I skip/move forward a line within the following
    > while loop?
    >
    > while (<FILE>) {
    > first = $_;
    > second = $_;
    > third = $_;
    > }
    >
    > # all below vars have different values
    > print $first;
    > print $second;
    > print $third;


    --untested--
    while(<FILE>){
    my $first = <FILE>;
    my $second = <FILE>;
    my $third = <FILE>;
    last;
    }
    --untested--

    This will get the first three lines - 'last' breaks the loop.

    HTH

    --
    Jim

    Copyright notice: all code written by the author in this post is
    released under the GPL. http://www.gnu.org/licenses/gpl.txt
    for more information.

    a fortune quote ...
    Eat drink and be merry, for tomorrow they may make it illegal.
    James Willmore, Oct 14, 2003
    #11
  12. John

    Anno Siegel Guest

    James Willmore <> wrote in comp.lang.perl.misc:
    > On Tue, 14 Oct 2003 11:50:05 GMT
    > "John" <> wrote:
    > > I'd like to move down a file and assign each line to a different
    > > variable. How can I skip/move forward a line within the following
    > > while loop?
    > >
    > > while (<FILE>) {
    > > first = $_;
    > > second = $_;
    > > third = $_;
    > > }
    > >
    > > # all below vars have different values
    > > print $first;
    > > print $second;
    > > print $third;

    >
    > --untested--
    > while(<FILE>){
    > my $first = <FILE>;
    > my $second = <FILE>;
    > my $third = <FILE>;
    > last;
    > }
    > --untested--


    Indeed...

    It drops the first line and reads the next three. It will also read
    past eof if there are fewer than four lines. That raises the question
    why "while" is there at all.

    See Abigail's solution for a correct one. (If only the first three
    lines are wanted, omit "redo" from Abigail's code.)

    Anno
    Anno Siegel, Oct 14, 2003
    #12
  13. James Willmore <> wrote:
    > --untested--
    > while(<FILE>){
    > my $first = <FILE>;
    > my $second = <FILE>;
    > my $third = <FILE>;
    > last;
    > }
    > --untested--
    >
    > This will get the first three lines - 'last' breaks the loop.


    That will get the 2nd, 3rd and 4th lines into $first, $second and $third
    respectively. Because they are my variables, they will be lost as soon
    as you exit the while loop.


    --
    Glenn Jackman
    NCF Sysadmin
    Glenn Jackman, Oct 14, 2003
    #13
  14. -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1

    -berlin.de (Anno Siegel) wrote in news:bmh8fa$pg5$2
    @mamenchi.zrz.TU-Berlin.DE:

    > Eric J. Roode <> wrote in comp.lang.perl.misc:
    >> You would do the above instead of
    >>
    >> @line = <DATA>;
    >>
    >> for ($i=0; $i<@line; $i++)
    >> {
    >> print "$i\t$line[$i]";
    >> }

    >
    > Why that instead of
    >
    > print "$_\t$line[$_]" for 0 .. $#line;
    >
    >:)


    Because I wanted to duplicate Helgi's structure as much as possible.
    Mostly I was surprised that he would represent the lines of the file as a
    hash instead of an array.

    - --
    Eric
    $_ = reverse sort $ /. r , qw p ekca lre uJ reh
    ts p , map $ _. $ " , qw e p h tona e and print

    -----BEGIN PGP SIGNATURE-----
    Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com>

    iQA/AwUBP4xUBWPeouIeTNHoEQJkIACbBL+eE4OIk9jTVoUStB9NMwlV/IIAoNfC
    Lh4pjqULQrydXIbpUPLzu+DM
    =5Jpi
    -----END PGP SIGNATURE-----
    Eric J. Roode, Oct 14, 2003
    #14
  15. John

    John Guest

    "Glenn Jackman" <> wrote in message
    news:...
    > James Willmore <> wrote:
    > > --untested--
    > > while(<FILE>){
    > > my $first = <FILE>;
    > > my $second = <FILE>;
    > > my $third = <FILE>;
    > > last;
    > > }
    > > --untested--
    > >
    > > This will get the first three lines - 'last' breaks the loop.

    >
    > That will get the 2nd, 3rd and 4th lines into $first, $second and $third
    > respectively. Because they are my variables, they will be lost as soon
    > as you exit the while loop.
    >
    >
    > --
    > Glenn Jackman
    > NCF Sysadmin
    >


    wow, so many answers :)

    can some1 pls elaborate why the variables start getting values from the 2nd
    line instead of the 1st one?
    what happens to the first line? goes into a void?
    John, Oct 15, 2003
    #15
  16. John <> wrote:
    > "Glenn Jackman" <> wrote in message...
    > > James Willmore <> wrote:
    > > > --untested--
    > > > while(<FILE>){
    > > > my $first = <FILE>;
    > > > my $second = <FILE>;
    > > > my $third = <FILE>;
    > > > last;
    > > > }
    > > > --untested--
    > > >
    > > > This will get the first three lines - 'last' breaks the loop.

    > >
    > > That will get the 2nd, 3rd and 4th lines into $first, $second and $third
    > > respectively. Because they are my variables, they will be lost as soon
    > > as you exit the while loop.

    >
    > wow, so many answers :)
    >
    > can some1 pls elaborate why the variables start getting values from the 2nd
    > line instead of the 1st one?
    > what happens to the first line? goes into a void?



    This construct:
    while (<FILE>) {...}
    sets $_ each time through the loop. So the first line is stored in $_,
    which will remain after the while loop ends.

    The perlop man page says:

    The following lines are equivalent:

    while (defined($_ = <STDIN>)) { print; }
    while ($_ = <STDIN>) { print; }
    while (<STDIN>) { print; }
    for (;<STDIN>;) { print; }
    print while defined($_ = <STDIN>);
    print while ($_ = <STDIN>);
    print while <STDIN>;

    This also behaves similarly, but avoids $_ :

    while (my $line = <STDIN>) { print $line }


    I've forgotten your original question. If it was how to read a file 3
    lines at a time, you could write:

    while (my $one = <FILE>) {
    my $two = <FILE>;
    my $three = <FILE>;
    # do something with $one, $two, $three.
    # $two and $three may be undefined.
    }

    --
    Glenn Jackman
    NCF Sysadmin
    Glenn Jackman, Oct 15, 2003
    #16
  17. John

    Roy Johnson Guest

    "John" <> wrote in message news:<Gy7jb.151558$>...
    > > James Willmore <> wrote:
    > > > --untested--
    > > > while(<FILE>){
    > > > my $first = <FILE>;
    > > > my $second = <FILE>;
    > > > my $third = <FILE>;
    > > > last;
    > > > }

    ....
    > can some1 pls elaborate why the variables start getting values from the 2nd
    > line instead of the 1st one?
    > what happens to the first line? goes into a void?


    No, it goes into $_. What did you think the "while(<FILE>)" line is
    doing?

    Each time you use the <> operator, you grab a new line. Your original
    example put the same grabbed line into each variable. The example
    above has four reads, and the first one is basically ignored.

    Reading the whole thing into an array (as suggested by Eric Roode) may
    be your most straightforward bet, depending on what you are really
    trying to do.

    Here's a variation on Abigail's recommendation for getting lines into
    three variables:

    READLOOP:{
    defined($_=<DATA>) or last READLOOP for (my ($v1, $v2, $v3));

    # Process lines here

    redo;
    }
    Roy Johnson, Oct 15, 2003
    #17
  18. On 14 Oct 2003 17:47:56 GMT
    Glenn Jackman <> wrote:

    > James Willmore <> wrote:
    > > --untested--
    > > while(<FILE>){
    > > my $first = <FILE>;
    > > my $second = <FILE>;
    > > my $third = <FILE>;
    > > last;
    > > }
    > > --untested--
    > >
    > > This will get the first three lines - 'last' breaks the loop.

    >
    > That will get the 2nd, 3rd and 4th lines into $first, $second and
    > $third respectively. Because they are my variables, they will be
    > lost as soon as you exit the while loop.


    --untested--
    my($first,$second,$third);
    while(<FILE>){
    $first = <FILE>;
    $second = <FILE>;
    $third = <FILE>;
    last;
    }
    --untested--

    -or-

    --untested--
    my($first,$second,$third);
    my $count = 1;
    while(<FILE>){
    $first = <FILE> if $count == 1;
    $second = <FILE> if $count == 2;
    $third = <FILE> if $count == 3;
    last if $count == 4;
    }
    --untested--

    -or-

    --untested--
    my($first,$second,$third);
    while(<FILE>){
    $first = <FILE> if $. == 1;
    $second = <FILE> if $. == 2;
    $third = <FILE> if $. == 3;
    last if $. == 4;
    }
    --untested--

    -or-

    --untested--
    my @lines = <FILE>;
    #access each ine as an element of the array
    --untested--

    -or-

    use one of the _many_ Perl modules relating to files.

    This question is a bit like "How do I print a formated line?". The
    accepted/first method is to use 'printf'. However, depending on what
    the end result is supposed to be and what else needs to be done and
    how the output is _supposed_ to look, you could use 'format'. Or, you
    could use 'sprintf' to format the string first, then use'print' to
    print the line (now containing the formated string).

    Try writing out what you want to do on paper _first_. The answer
    _may_ just pop off the page at you.

    HTH

    --
    Jim

    Copyright notice: all code written by the author in this post is
    released under the GPL. http://www.gnu.org/licenses/gpl.txt
    for more information.

    a fortune quote ...
    Whistler's Law: You never know who is right, but you always know
    who is in charge.
    James Willmore, Oct 15, 2003
    #18
  19. John

    Roy Johnson Guest

    James Willmore <> wrote in message news:<>...
    > --untested--
    > my($first,$second,$third);
    > while(<FILE>){
    > $first = <FILE>;


    You're still getting the first line into $_, for no apparent reason.
    You might consider
    until(eof FILE)
    instead of
    while(<FILE>)

    > $second = <FILE>;
    > $third = <FILE>;
    > last;


    Or, since you're breaking out of the loop on the first pass, just
    don't have a loop.

    > my $count = 1;
    > while(<FILE>){
    > $first = <FILE> if $count == 1;
    > $second = <FILE> if $count == 2;
    > $third = <FILE> if $count == 3;
    > last if $count == 4;
    > }
    > --untested--


    You need to increment $count each time, or you're going to repeatedly
    assign $_ and $first, and none of the others. Is it not possible for
    you to test the solutions you propose?

    > --untested--
    > my @lines = <FILE>;
    > #access each ine as an element of the array
    > --untested--


    That's a winner, at least.
    Roy Johnson, Oct 15, 2003
    #19
  20. John

    John Guest

    "Roy Johnson" <> wrote in message
    news:...
    > "John" <> wrote in message

    news:<Gy7jb.151558$>...
    > > > James Willmore <> wrote:
    > > > > --untested--
    > > > > while(<FILE>){
    > > > > my $first = <FILE>;
    > > > > my $second = <FILE>;
    > > > > my $third = <FILE>;
    > > > > last;
    > > > > }

    > ...
    > > can some1 pls elaborate why the variables start getting values from the

    2nd
    > > line instead of the 1st one?
    > > what happens to the first line? goes into a void?

    >
    > No, it goes into $_. What did you think the "while(<FILE>)" line is
    > doing?
    >
    > Each time you use the <> operator, you grab a new line. Your original
    > example put the same grabbed line into each variable. The example
    > above has four reads, and the first one is basically ignored.
    >
    > Reading the whole thing into an array (as suggested by Eric Roode) may
    > be your most straightforward bet, depending on what you are really
    > trying to do.
    >
    > Here's a variation on Abigail's recommendation for getting lines into
    > three variables:
    >
    > READLOOP:{
    > defined($_=<DATA>) or last READLOOP for (my ($v1, $v2, $v3));
    >
    > # Process lines here
    >
    > redo;
    > }


    Roy and Glen,
    Thanks once again :)
    John, Oct 16, 2003
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. news.frontiernet.net
    Replies:
    6
    Views:
    1,121
    news.frontiernet.net
    Apr 16, 2004
  2. scad
    Replies:
    23
    Views:
    1,163
    Alf P. Steinbach
    May 17, 2009
  3. Merciadri Luca
    Replies:
    4
    Views:
    809
  4. Eduardo78
    Replies:
    0
    Views:
    248
    Eduardo78
    Nov 3, 2005
  5. Andrew Tomazos
    Replies:
    2
    Views:
    614
    Nobody
    Dec 12, 2011
Loading...

Share This Page