How does one move down a line in a file?

J

John

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
 
A

Anno Siegel

John said:
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 = said:
# all below vars have different values
print $first;
print $second;
print $third;

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

Anno
 
A

Anno Siegel

Abigail said:
John ([email protected]) wrote on MMMDCXCVI September MCMXCIII in
<URL:~~ 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
 
J

John

Anno Siegel said:
John said:
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 = said:
# 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);
 
T

Tad McClellan

John said:
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
}
 
H

Helgi Briem

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{$_}";
}
 
T

Tad McClellan

[ 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' $!";
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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-----
 
A

Anno Siegel

Abigail said:
Anno Siegel ([email protected]) wrote on MMMDCXCVI
September MCMXCIII in <URL:[...]

"" > 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
 
A

Anno Siegel

Eric J. Roode said:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

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
 
J

James Willmore

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.
 
A

Anno Siegel

James Willmore said:
--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
 
G

Glenn Jackman

James Willmore said:
--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.
 
E

Eric J. Roode

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

(e-mail address removed)-berlin.de (Anno Siegel) wrote in @mamenchi.zrz.TU-Berlin.DE:
Eric J. Roode said:
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-----
 
J

John

Glenn Jackman said:
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?
 
G

Glenn Jackman

John said:
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.
}
 
R

Roy Johnson

John said:
....
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;
}
 
J

James Willmore

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.
 
R

Roy Johnson

James Willmore said:
--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( said:
$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.
 
J

John

Roy Johnson said:
...
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;
}[/QUOTE]

Roy and Glen,
Thanks once again :)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top