How to read a given number of lines?

P

Peng Yu

I want to give a given number of lines. Current, I have to write the
following code to read, for example, 3 lines. Is there a subroutine to
read a given number of lines in an array?

$line1=<IN>;
$line2=<IN>;
$line3=<IN>;

Regards,
Peng
 
R

Ralph Malph

I want to give a given number of lines. Current, I have to write the
following code to read, for example, 3 lines. Is there a subroutine to
read a given number of lines in an array?

$line1=<IN>;
$line2=<IN>;
$line3=<IN>;
This will store the lines in the
cleverly named array @lines.
I've set $limit to 3 as in your short example
but obviously this works for any limit.
Always be sure to double check any user-inputed values!
--------------------------------
my @lines;
my $limit=3;
my $counter=0;
while($counter < $limit){
$lines[$counter] = <IN> ;
$counter++;
}
 
M

Mart van de Wege

Ralph Malph said:
I want to give a given number of lines. Current, I have to write the
following code to read, for example, 3 lines. Is there a subroutine to
read a given number of lines in an array?

$line1=<IN>;
$line2=<IN>;
$line3=<IN>;
This will store the lines in the
cleverly named array @lines.
I've set $limit to 3 as in your short example
but obviously this works for any limit.
Always be sure to double check any user-inputed values!
--------------------------------
my @lines;
my $limit=3;
my $counter=0;
while($counter < $limit){
$lines[$counter] = <IN> ;
$counter++;
}

or:

my @lines;
my $limit = 3;
for my $line(1..$limit) {
$lines[$line] = <IN>
}

But then again I have a personal dislike of counters and flags, so I
tend to look for ways to avoid using them.
 
M

Mart van de Wege

Mart van de Wege said:
Ralph Malph said:
I want to give a given number of lines. Current, I have to write the
following code to read, for example, 3 lines. Is there a subroutine to
read a given number of lines in an array?

$line1=<IN>;
$line2=<IN>;
$line3=<IN>;
This will store the lines in the
cleverly named array @lines.
I've set $limit to 3 as in your short example
but obviously this works for any limit.
Always be sure to double check any user-inputed values!
--------------------------------
my @lines;
my $limit=3;
my $counter=0;
while($counter < $limit){
$lines[$counter] = <IN> ;
$counter++;
}

or:

my @lines;
my $limit = 3;
for my $line(1..$limit) {
$lines[$line] = <IN>
}

But then again I have a personal dislike of counters and flags, so I
tend to look for ways to avoid using them.

And that was an off-by-one error. Saw it as I hit 'post'.

So the correct code would of course be:

my @lines;
my $limit = 3;
for my $line(0..$limit-1) {
$lines[$line] = <IN>
}
 
R

Ralph Malph

Mart van de Wege said:
Ralph Malph said:
On 6/8/2010 12:14 PM, Peng Yu wrote:
I want to give a given number of lines. Current, I have to write the
following code to read, for example, 3 lines. Is there a subroutine to
read a given number of lines in an array?

$line1=<IN>;
$line2=<IN>;
$line3=<IN>;
This will store the lines in the
cleverly named array @lines.
I've set $limit to 3 as in your short example
but obviously this works for any limit.
Always be sure to double check any user-inputed values!
--------------------------------
my @lines;
my $limit=3;
my $counter=0;
while($counter< $limit){
$lines[$counter] =<IN> ;
$counter++;
}

or:

my @lines;
my $limit = 3;
for my $line(1..$limit) {
$lines[$line] =<IN>
}

But then again I have a personal dislike of counters and flags, so I
tend to look for ways to avoid using them.

And that was an off-by-one error. Saw it as I hit 'post'.

So the correct code would of course be:

my @lines;
my $limit = 3;
for my $line(0..$limit-1) {
$lines[$line] =<IN>
}
In some senses you original code was correct although
it didn't fill $lines[0].
As required, it read a certain number of lines into an array.
Nonetheless, I suggest you start disliking silly errors
more than you dislike counters and flags.
HTH
 
W

Willem

Ben Morrow wrote:
) Better would be
)
) my @lines;
) push @lines, <IN> for 1..3;
)
) though I would probably rather have
)
) my @lines = map <IN>, 1..3;
)
) since I don't like variable declarations just hanging around not doing
) anything useful.

BZZT!

Both of your examples will read the entire file into @lines.
Left as an exercise to figure out why this is and how to fix it.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
R

Ralph Malph

Ben Morrow wrote:
) Better would be
)
) my @lines;
) push @lines,<IN> for 1..3;
)
) though I would probably rather have
)
) my @lines = map<IN>, 1..3;
)
) since I don't like variable declarations just hanging around not doing
) anything useful.

BZZT!

Both of your examples will read the entire file into @lines.
Left as an exercise to figure out why this is and how to fix it.
Q: "How to fix it".
A: They need to stop trying to be so fucking clever. Clever kills.
 
W

Willem

Ben Morrow wrote:
) 'They' in this case being me? I wasn't trying to be clever, I was trying
) to write the code in a simple and obvious way. Counting indices by hand
) is much easier to get wrong than letting perl count them for you.

You mean like: for (0..2) { $lines[$_] = <IN> }

But in any case, this mistake is not a cleverness one,
because the exact same problem exists in the code:

for (my $i = 0; $i < 3; $i++) {
push @lines, <IN>;
}

Which I would hardly call 'clever'.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
M

Marc Girod

You mean like: for (0..2) { $lines[$_] = <IN> }

I'am not smart enough to not try being clever.
Besides (and for wrong reasons: I used to like Lisp), I like maps.
So, I was thinking of the following minimal(?) fix(?):

my @lines = map scalar <IN>, 1..3;

Marc
 
U

Uri Guttman

BM> Quoth Willem said:
Ben Morrow wrote:
) 'They' in this case being me? I wasn't trying to be clever, I was trying
) to write the code in a simple and obvious way. Counting indices by hand
) is much easier to get wrong than letting perl count them for you.

You mean like: for (0..2) { $lines[$_] = <IN> }

BM> Mmm, I suppose. I think my problem with that is that I just dislike
BM> array indices other than [0] and [-1]: I think of arrays as 'frozen
BM> lists', so either you iterate over the whole thing or you attack it from
BM> the ends.

amusing viewpoint but what about random accesses, direct accesses (it
happens), splicing (both inserts and deletes), etc. true, i do what you
say most of the time but i still keep those other things in my
toolbox. :)

uri
 
M

Mart van de Wege

Ralph Malph said:
my @lines;
my $limit = 3;
for my $line(1..$limit) {
$lines[$line] =<IN>
}

But then again I have a personal dislike of counters and flags, so I
tend to look for ways to avoid using them.

And that was an off-by-one error. Saw it as I hit 'post'.

So the correct code would of course be:

my @lines;
my $limit = 3;
for my $line(0..$limit-1) {
$lines[$line] =<IN>
}
In some senses you original code was correct although
it didn't fill $lines[0].
As required, it read a certain number of lines into an array.
Nonetheless, I suggest you start disliking silly errors
more than you dislike counters and flags.
HTH

You know, if you want your advice to be taken seriously, it would be
better not to behave like a complete twit.

Mart
 
B

bankair

I want to give a given number of lines. Current, I have to write the
following code to read, for example, 3 lines. Is there a subroutine to
read a given number of lines in an array?

$line1=<IN>;
$line2=<IN>;
$line3=<IN>;

Hi,

May be the special var "$." (line NBR of the last read file handle)
could help :
my @lines;
while (<>) { push @lines,$_ if($.<4) }

Regards,
Alexandre
 
U

Uri Guttman

b> Hi,

b> May be the special var "$." (line NBR of the last read file handle)
b> could help :
b> my @lines;
b> while (<>) { push @lines,$_ if($.<4) }

and what happens to the lines after the third one? that will read to eof
which is likely not wanted.

better to invert the loop:

while ( $. < 4 ) {
push @lines, scalar <> ;
}

or for those lovers of one liners:

push @lines, scalar <> while $. < 4 ;

uri
 
B

bankair

  >> I want to give a given number of lines. Current, I have to write the
  >> following code to read, for example, 3 lines. Is there a subroutine to
  >> read a given number of lines in an array?
  >>
  >> $line1=<IN>;
  >> $line2=<IN>;
  >> $line3=<IN>;

  b> Hi,

  b> May be the special var "$." (line NBR of the last read file handle)
  b> could help :
  b> my @lines;
  b> while (<>) { push @lines,$_ if($.<4) }

and what happens to the lines after the third one? that will read to eof
which is likely not wanted.

better to invert the loop:

while ( $. < 4 ) {
        push @lines, scalar <> ;

}

or for those lovers of one liners:

        push @lines, scalar <> while $. < 4 ;

Ah ! Your "scalar <>" (thank you) gave me another idea :

my @lines = grep {defined $_} map {scalar <>} (1..3);
 
M

Martijn Lievaart

b> Hi,

b> May be the special var "$." (line NBR of the last read file handle)
b> could help :
b> my @lines;
b> while (<>) { push @lines,$_ if($.<4) }

and what happens to the lines after the third one? that will read to eof
which is likely not wanted.

better to invert the loop:

while ( $. < 4 ) {
push @lines, scalar <> ;
}

or for those lovers of one liners:

push @lines, scalar <> while $. < 4 ;

Those have the potential of an infinite loop when the file has less than
3 lines. Besides, even when fixed, the 'push @lines, scalar <>' pushes
undef at eof, so I very much doubt this is what you want.

So I guess the best option (assuming you want to exit early at eof, not
push undefs):


while (<>) {
last if ($.>=4)
push @lines,$_;
}

Eventually followed by

push @lines, undef for ($. .. 3);

If you do want undefs for missing lines.

M4
 
J

Justin C

I want to give a given number of lines. Current, I have to write the
following code to read, for example, 3 lines. Is there a subroutine to
read a given number of lines in an array?

$line1=<IN>;
$line2=<IN>;
$line3=<IN>;

Regards,
Peng


The variable $. holds the current line number for the last filehandle
accessed. It may be useful to you, see perldoc perlvar for details.

Justin.
 
P

Peng Yu

You mean like: for (0..2) { $lines[$_] = <IN> }

I'am not smart enough to not try being clever.
Besides (and for wrong reasons: I used to like Lisp), I like maps.
So, I was thinking of the following minimal(?) fix(?):

my @lines = map scalar <IN>, 1..3;

I don't understand why 'scalar' has to be used. Would you please let
me know where I should read in man page to understand file handle in
scalar and list context.
 
M

Marc Girod

I don't understand why 'scalar' has to be used. Would you please let
me know where I should read in man page to understand file handle in
scalar and list context.

I/O Operators in perlop?
In scalar context, evaluating a filehandle in angle brackets
yields the
next line from that file (the newline, if any, included), or
"undef" at
end-of-file or on error.
....
If a <FILEHANDLE> is used in a context that is looking for a
list, a list
comprising all input lines is returned, one line per list
element.

and then, of course, scalar in perlfunc...
scalar EXPR
Forces EXPR to be interpreted in scalar context and
returns the
value of EXPR.

Marc
 
M

Mart van de Wege

Peng Yu said:
You mean like: for (0..2) { $lines[$_] = <IN> }

I'am not smart enough to not try being clever.
Besides (and for wrong reasons: I used to like Lisp), I like maps.
So, I was thinking of the following minimal(?) fix(?):

my @lines = map scalar <IN>, 1..3;

I don't understand why 'scalar' has to be used. Would you please let
me know where I should read in man page to understand file handle in
scalar and list context.

As Marc pointed out, using the readline operator <> in scalar context
reads only one line.

Why it is necessary here is because the above statement would normally
evaluate <> in list context. I'm a bit unclear if that is because of the
array assignment or the map function. I believe it is the map function
forcing a list context here, but I could be wrong. Even if I am,
assigning to an array definitely forces list context.

Mart
 
D

Dr.Ruud

Peng said:
I want to give a given number of lines. Current, I have to write the
following code to read, for example, 3 lines. Is there a subroutine to
read a given number of lines in an array?

$line1=<IN>;
$line2=<IN>;
$line3=<IN>;

$ echo -e 'a\nb\nc\nd\ne\n' | perl -wle'

sub get_lines {
my ( $fh, $max, $aref )= @_;
my $count;
while ( ++$count <= $max and defined( my $line= <$fh> ) ) {
push @$aref, $line;
}
return $count;
}

my @lines;
get_lines +STDIN, 2, \@lines;
print for @lines;
'
a

b
 

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

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top