Minimalist
Minimalist

Reputation: 975

Output the line numbers where a string appears

I am trying to determine how many time a string, Apples appears in a text file and in which lines it appears.

The script outputs incorrect line numbers, instead it outputs numbers consecutively (1,2,..) and not the correct lines for the word.

file.txt

    Apples
    Grapes
    Oranges
    Apples

Goal Output

Apples appear 2 times in this file
Apples appear on these lines: 1, 4,

Instead my output as illustrated from the code below is:

Apples appear 2 times in this file
Apples appear on these lines: 1, 2,

Perl

my $filename = "<file.txt";

open( TEXT, $filename );

$initialLine = 10;    ## holds the number of the line
$line        = 0;
$counter     = 0;

# holder for line numbers
@lineAry = ();

while ( $line = <TEXT> ) {

    chomp( $line );

    if ( $line =~ /Apples/ ) {

        while ( $line =~ /Apples/ig ) {
            $counter++;
        }

        push( @lineAry, $counter );

        $initialLine++;
    }
}
close( TEXT );

# print "\n\n'Apples' occurs $counter times in file.\n";
print "Apples appear $counter times in this file\n";
print "Apples appear on these lines: ";

foreach $a ( @lineAry ) {
    print "$a, ";
}

print "\n\n";

exit;

Upvotes: 0

Views: 133

Answers (2)

Borodin
Borodin

Reputation: 126722

There are a number of problems with your code, but the reason for the line numbers being printed wrongly is that you are incrementing your variable $counter once each time Apples appears on a line and saving it to @lineAry. That is different from the number of the line where the string appears, and the easiest fix is to use the built-in variable $. which represents the number of times a read has been performed on the file handle

In addition, I would encourage you to use lexical file handles, and the three-parameter form of open, and check that every call to open has succeeded

You never use the value of $initialLine, and I don't understand why you have initialised it to 10

I would write it like this

use strict;
use warnings 'all';

my $filename = 'file.txt';

open my $fh, '<', $filename or die qq{Unable to open "$filename" for input: $!};

my @lines;
my $n;

while ( <$fh> ) {
    push @lines, $. if /apples/i;
    ++$n while /apples/ig;
}

print "Apples appear $n times in this file\n";
print "Apples appear on these lines: ", join( ', ', @lines ), "\n\n";

output

Apples appear 2 times in this file
Apples appear on these lines: 1, 4

Upvotes: 5

user1717259
user1717259

Reputation: 2863

Change

push(@lineAry, $counter);

to

push(@lineAry, $.);

$. is a variable that stores the line number when using perl's while (<>).

The alternative, if you want to use your $counter variable, is that you move the increment to increment on every line, not on every match.

Upvotes: 4

Related Questions