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

I need to write a Perl script that counts all occurrences of the word and in the standard input file. If the word is an “and”, print out the number of word in the line of text and the line number of the line. I have tried to write this, however I am stuck and was I have written is not working. This is what I have so far.
#!/usr/bin/perl $wordcount=0; $line = <STDIN>; chomp($line); WHILE ($line ne "") { @array=split(/ /, $line); for ($i=1; $i<@array; i++) { print $i; } if ( @array =~ /^and/gi) { $wordcount += @array; } $line= <STDIN>; } print("Total number of works is $wordcount \n");
Trying to generate an output that says something like this for each word occurence:
The word and occurred in Line 1 as the 7th word The word and occurred in Line 1 as the 11th word

Replies are listed 'Best First'.
Re: tracking words in lines
by davido (Cardinal) on Nov 12, 2004 at 19:13 UTC

    Try this:

    use strict; use warnings; while ( my $line = <DATA> ) { next unless $line =~ /\band\b/; chomp $line; my @words = split /\s+/, $line; my $location = 0; my @locations; foreach ( @words ) { $location++; push @locations, $location if m/\band\b/; } local $" = ", "; print "Line $.: 'and' appears as word @locations.\n"; } __DATA__ This is a test and a test and a test.

    Dave

      I like your code for this one. Just a question though regarding your regex.

      Is your m/\band\b/ better than my method of m/^and$/? Wouldn't they be doing exactly the same thing?



      "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

      sulfericacid

        There is a difference. Consider the following:

        son-and-law I can't promise anything (and never will). People should carpool--and in some cases they do--since it saves gas.

        m/^and$/ will miss the 'and' in these cases, even though it is there. I don't know whether the OP wants that or not, as he didn't really specify edge cases. If such edge cases should be disallowed, my code would need a minor modification so as to not attempt to print anything if @locations is empty.


        Dave

Re: tracking words in lines
by sulfericacid (Deacon) on Nov 12, 2004 at 18:57 UTC
    This was written quickly but was tested. This should do what you want.
    #!/usr/bin/perl use warnings; use strict; my $wordcount = 0; my $linenumber = 0; my $wordnumber = 0; my $findword = "and"; open(FILE, "< input.txt") or die "Cannot open file: $!"; my @lines = <FILE>; close(FILE) or die "Cannot close file: $!"; foreach my $line (@lines) { $linenumber++; my @words = split(/\s+/, $line); foreach my $word (@words) { $wordnumber++; if ($word =~ m/^and$/) { print qq(The word "$findword" occured in line $linenumber a +t word $wordnumber\n); } } $wordnumber = 0; }

    UPDATE: Fixed word splitting in regards to Enlil's message:

    "but split '',$line is probably better than / /, if someone puts two spaces you might want split, / +/,$line =) "

    Thanks!



    "Age is nothing more than an inaccurate number bestowed upon us at birth as just another means for others to judge and classify us"

    sulfericacid
Re: tracking words in lines
by TedPride (Priest) on Nov 12, 2004 at 20:41 UTC
    index -> regex -> split
    use strict; my $word = 'and'; while (<DATA>) { if (index($_, $word) > -1) { while (m/(?:^|[^a-zA-Z'])$word[^a-zA-Z']/gi) { print "The word\n$word\noccured in line " . ($.-1) . " as +the " . ends(scalar(split(/[^a-zA-Z']+/, substr($_, 0, pos($_) - 1 +)))) . " word.\n\n"; } } } BEGIN { my @ends = ('','st','nd','rd'); sub ends { return $_[0] . @ends[$_[0] % 10] if $_[0] % 10 < 4 && $_[0] % +10 > 0 && int($_[0] / 10) != 1; return $_[0] . 'th'; } } __DATA__ Four score and seven years ago our fathers brought forth, upon this co +ntinent, a new nation, conceived in liberty, and dedicated to the proposition tha +t "all men are created equal" Now we are engaged in a great civil war, testing whether that nation, +or any nation so conceived, and so dedicated, can long endure. We are met on +a great battle field of that war. We have come to dedicate a portion of it, as + a final resting place for those who died here, that the nation might live. Thi +s we may, in all propriety do. But, in a larger sense, we can not dedicate -- we + can not consecrate -- we can not hallow, this ground -- The brave men, living +and dead, who struggled here, have hallowed it, far above our poor power to add +or detract. The world will little note, nor long remember what we say here; while +it can never forget what they did here.