# How to read a given number of lines?

#### Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

•  Subject
• Author
• Posted on

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

## Re: How to read a given number of lines?

On 6/8/2010 12:14 PM, Peng Yu wrote:

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++;
}

## Re: How to read a given number of lines?

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.

--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.

## Re: How to read a given number of lines?

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>
}
--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.

## Re: How to read a given number of lines?

On 6/8/2010 1:14 PM, Mart van de Wege wrote:

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

## Re: How to read a given number of lines?

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

Mart

--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.

## Re: How to read a given number of lines?

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.

Ben

## Re: How to read a given number of lines?

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!

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

## Re: How to read a given number of lines?

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

## Re: How to read a given number of lines?

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

## Re: How to read a given number of lines?

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.

## Re: How to read a given number of lines?

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

## Re: How to read a given number of lines?

As Marc pointed out, using the readline operator <> in scalar context

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

--
"We will need a longer wall when the revolution comes."
--- AJS, quoting an uncertain source.

## Re: How to read a given number of lines?

map always evaluates its first argument (EXPR or BLOCK) in list context.
This makes it possible to change the length of the returned list.

Ben

## Re: How to read a given number of lines?

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

The original buggy code was essentially

for (1..3) { \$lines[\$_] = <IN> }

and the use of explicit subscripts disguises the fact that there's an
extra 'undef' element on the beginning.

I suspect that anyone approaching that code who didn't have a background
in C *would* call it clever, or at any rate much more complicated and
less comprehensible than a simple

for (1..3)

Something like

repeat (3)

would be even simpler, of course, but unfortunately Perl doesn't allow
modules to create new syntax like that[0].

Ben

[0] ...without support code that will make you go blind.
c.f. Devel::Declare, and/or source filters.

## Re: How to read a given number of lines?

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

--
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------

## Re: How to read a given number of lines?

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

## Re: How to read a given number of lines?

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

uri

--
Uri Guttman  ------  uri@stemsystems.com  --------  http://www.sysarch.com --
-----  Perl Code Review , Architecture, Development, Training, Support ------
---------  Gourmet Hot Cocoa Mix  ----  http://bestfriendscocoa.com ---------

## Re: How to read a given number of lines?

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

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

## Re: How to read a given number of lines?

On Wed, 09 Jun 2010 04:17:33 -0400, Uri Guttman wrote:

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