Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks, Just a quick task i need help with as i dont know how to do it. I need to be able to read each line in a file until a word for the second time.

do { $_ = <> } until /formulae/;

Is what i have so far, which finds the first 'formulae' word. I need to be able to find the second...

Ne Ideas? Cheers, Steve

20031027 Edit by Corion: Changed title from 'second match...'

  • Comment on Finding the second line an item appears on

Replies are listed 'Best First'.
Re: Finding the second line an item appears on
by Abigail-II (Bishop) on Oct 27, 2003 at 16:56 UTC
    You're almost there:
    #!/usr/bin/perl use strict; use warnings; my $count; do {$_ = <DATA>; print} until /formulae/ && ++ $count == 2; __DATA__ One line two line formulae blue line red line formulae more line more line formulae final line
    That will print:
    One line two line formulae blue line red line formulae

    Abigail

Re: Finding the second line an item appears on
by dreadpiratepeter (Priest) on Oct 27, 2003 at 16:42 UTC
    my $cnt=0; while (my $line = <>) { $cnt++ if $line =~ /formulae/; last if $cnt>1; } if ($cnt>1) { # got what we wanted } else { # word didn't appear twice }
    I'm sure it can be done more succinctly, but this should make obvious what is going on.

    UPDATE: ops! thanks Albannach. fixed code above.


    -pete
    "Worry is like a rocking chair. It gives you something to do, but it doesn't get you anywhere."
Re: Finding the second line an item appears on
by hardburn (Abbot) on Oct 27, 2003 at 17:03 UTC

    Copy-and-paste your search to the line just below it:

    do { $_ = <> } until /formulae/; do { $_ = <> } until /formulae/;

    Sure, it isn't fancy, but it doesn't rely on any counter variables, either.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    :(){ :|:&};:

    Note: All code is untested, unless otherwise stated

Re: Finding the second line an item appears on
by monktim (Friar) on Oct 27, 2003 at 18:48 UTC
    The other answers look good if formulae is guaranteed to exist on at most 1 line at a time. If it can appear twice on the same line, this will work.
    use strict; my $i; while (<DATA>) { my @m = ($_ =~ /formulae/g); $i += @m; } print "Found $i matches\n"; __DATA__ message one message two formulae formulae message threee
Re: second match...
by Anonymous Monk on Oct 27, 2003 at 17:18 UTC
    while(<>){print&&(/formula/.../formula/)=~/E0$/&&last}
Re: Finding the second line an item appears on
by Anonymous Monk on Oct 27, 2003 at 16:44 UTC

    Many ways of doing this, for instance, this is rather inelegant but shows the logic clearly:

    my $count = 0; while (<>) { if (/formulae/) { $count++; } if ($count == 2) { print "Found 2nd\n"; } }

    Or you can just change your do-loop a bit:

    $count = 0; do {$count++; $_ = <> } until ((/formulae/) && ($count == 2))
      Your second example doesn't work. It will match the third line, if it contains formulae, otherwise it will fail.


      -pete
      "Worry is like a rocking chair. It gives you something to do, but it doesn't get you anywhere."
Re: Finding the second line an item appears on
by Art_XIV (Hermit) on Oct 27, 2003 at 16:47 UTC

    This is a bit brute force, but I'm sure one of the other monks has a more elegant way...

    my @matches; while (<FILE>) { push @matches, $_ if /formulae/; last if scalar @matches == 2; }

    You'd be out of luck with this one, though, if 'formulae' could occur more than once per line and still have to stop.