How to read a given number of lines?

Discussion in 'Perl Misc' started by Peng Yu, Jun 8, 2010.

  1. Peng Yu

    Peng Yu Guest

    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
     
    Peng Yu, Jun 8, 2010
    #1
    1. Advertising

  2. Peng Yu

    Ralph Malph Guest

    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++;
    }
     
    Ralph Malph, Jun 8, 2010
    #2
    1. Advertising

  3. Ralph Malph <> writes:

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

    --
    "We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.
     
    Mart van de Wege, Jun 8, 2010
    #3
  4. Mart van de Wege <> writes:

    > Ralph Malph <> writes:
    >
    >> 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>
    }
    --
    "We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.
     
    Mart van de Wege, Jun 8, 2010
    #4
  5. Peng Yu

    Ralph Malph Guest

    On 6/8/2010 1:14 PM, Mart van de Wege wrote:
    > Mart van de Wege<> writes:
    >
    >> Ralph Malph<> writes:
    >>
    >>> 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
     
    Ralph Malph, Jun 8, 2010
    #5
  6. Peng Yu

    Willem Guest

    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
     
    Willem, Jun 8, 2010
    #6
  7. Peng Yu

    Ralph Malph Guest

    On 6/8/2010 1:42 PM, Willem wrote:
    > 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.
     
    Ralph Malph, Jun 8, 2010
    #7
  8. Peng Yu

    Willem Guest

    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
     
    Willem, Jun 8, 2010
    #8
  9. Peng Yu

    Marc Girod Guest

    On Jun 8, 9:14 pm, Willem <> wrote:

    > 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
     
    Marc Girod, Jun 8, 2010
    #9
  10. Peng Yu

    Uri Guttman Guest

    >>>>> "BM" == Ben Morrow <> writes:

    BM> Quoth 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> }


    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 ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Jun 9, 2010
    #10
  11. Ralph Malph <> writes:

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


    --
    "We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.
     
    Mart van de Wege, Jun 9, 2010
    #11
  12. Peng Yu

    bankair Guest

    On Jun 8, 6: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>;


    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
     
    bankair, Jun 9, 2010
    #12
  13. Peng Yu

    Uri Guttman Guest

    >>>>> "b" == bankair <> writes:

    b> On Jun 8, 6: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>;


    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 ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
     
    Uri Guttman, Jun 9, 2010
    #13
  14. Peng Yu

    bankair Guest

    On Jun 9, 10:17 am, "Uri Guttman" <> wrote:
    > >>>>> "b" == bankair  <> writes:

    >
    >   b> On Jun 8, 6: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>;
    >
    >   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);
     
    bankair, Jun 9, 2010
    #14
  15. On Wed, 09 Jun 2010 04:17:33 -0400, Uri Guttman wrote:

    >>>>>> "b" == bankair <> writes:

    >
    > b> On Jun 8, 6: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>;

    >
    > 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
     
    Martijn Lievaart, Jun 9, 2010
    #15
  16. Peng Yu

    Justin C Guest

    On 2010-06-08, 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>;
    >
    > 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.

    --
    Justin C, by the sea.
     
    Justin C, Jun 9, 2010
    #16
  17. Peng Yu

    Peng Yu Guest

    On Jun 8, 3:58 pm, Marc Girod <> wrote:
    > On Jun 8, 9:14 pm, Willem <> wrote:
    >
    > > 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.
     
    Peng Yu, Jun 9, 2010
    #17
  18. Peng Yu

    Marc Girod Guest

    On Jun 9, 4:48 pm, Peng Yu <> wrote:

    > 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
     
    Marc Girod, Jun 9, 2010
    #18
  19. Peng Yu <> writes:

    > On Jun 8, 3:58 pm, Marc Girod <> wrote:
    >> On Jun 8, 9:14 pm, Willem <> wrote:
    >>
    >> > 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

    --
    "We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.
     
    Mart van de Wege, Jun 10, 2010
    #19
  20. Peng Yu

    Dr.Ruud Guest

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


    $ 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

    --
    Ruud
     
    Dr.Ruud, Jun 12, 2010
    #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. Lord0
    Replies:
    1
    Views:
    573
    Thomas Weidenfeller
    Apr 19, 2006
  2. Joe Wright
    Replies:
    0
    Views:
    526
    Joe Wright
    Jul 27, 2003
  3. chiara
    Replies:
    6
    Views:
    477
    Barry Schwarz
    Oct 6, 2005
  4. 2Barter.net
    Replies:
    0
    Views:
    372
    2Barter.net
    Dec 13, 2006
  5. Casey Hawthorne
    Replies:
    385
    Views:
    5,694
    ng2010
    Apr 4, 2010
Loading...

Share This Page