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

Hi all,

Long story short I'm trying to compare two HTML files for differences. I already have a program that strips the HTML and puts each word on its own line, I'm happy with this. The output is two new files that I then want to compare differences between.

I now want a second program that does the comparing. I go ahead and open both files and save them to a new array:

open FILE1, $ARGV[0] or die "Couldn't open file: $!"; my @lines1 = <FILE1>; close(FILE1);

Same for a second file. I then try to compare them line-by-line using a foreach loop on the first same file. The exact code I use for the comparison is if($lines1[$_] eq $lines2[$_]). However I get the error:

Argument "line example here" isn't numeric in array element at compare.pl line 14.

This confuses me, because I can access them exactly the same way outside the array, $lines[0] etc. Is there something obvious I'm missing? I'm fairly new to Perl so always happy to learn some theory behind the code. Thanks

Replies are listed 'Best First'.
Re: File to array and reading back
by roboticus (Chancellor) on Jun 19, 2012 at 10:26 UTC

    Kris0r:

    Apparently, I've not had enough coffee this morning--I missed your last sentence. It's complaining that $_ is not numeric. So I'm guessing you're iterating over the list of strings rather than a list of numbers when processing the array, something like:

    my @array1 = ('foo', 'bar', 'baz'); my @array2 = ('zim', 'zam', 'baz'); # should work: for (0 .. $#array1) { if ($array1[$_] eq $array2[$_]) { print "match! $array[$_]\n" } else { print "mismatch $array1[$_] ne $array2[$_] } } # should give a similar error: for (@array1) { if ($array1[$_] eq $array2[$_]) { print "match! $array[$_]\n" } else { print "mismatch $array1[$_] ne $array2[$_] } }

    Try printing the value of $_ before using it as an array index, and you'll see what perl is complaining about.

    You're not showing your comparison code, but from the error message, I'm guessing you're using the numeric equality operator (==) rather than the string equality operator (eq) to compare lines.

    Update: Rewrote node after re-reading OP and realizing my goof.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      Edit: Can't write quick enough! You were correct, I think I was trying to use the string itself as its place in the array. Your example is easier to follow than my workaround so I'll try that. Thanks!

      I did show it, albeit it was inline with other text so easy to miss.

      if($lines1[$_] eq $lines2[$_])

      I have fixed it by creating a basic for loop and iterating through using the size of the array as the limit. Which now seems to work:

      for(my $i = 0; $i < @lines1; $i++) { if($lines1[$i] eq $lines2[$i]) { print("same.\n"); } else { $difference++; }

      That seems a bit archaic and far too long to be Perl, but I wrote it and it works so I'm happy to use it!

Re: File to array and reading back
by ww (Archbishop) on Jun 19, 2012 at 11:39 UTC

    I think I smell a fish... since when does eq throw a "not numeric?"

    perl -e "my $lines1 = 7; my $lines2=8; if ($lines1 eq $lines2) {print +'lines are eq';} else {print 'wtf';}" wtf perl -e "my $lines1 ='foo'; my $lines2='bar'; if ($lines1 eq $lines2) +{print 'lines are eq';} else {print 'wtf';}" wtf perl -e "my $lines1 ='foo'; my $lines2='foo'; if ($lines1 eq $lines2) +{print 'lines are eq';} else {print 'wtf';}" lines are eq

    Is there something I'm missing or do the reported (code + error) seem to be misaligned?
    Phrased another way, are you sure if($lines1[$_] eq $lines2[$_]) is line 14 -- i.e., the source of the "not numeric"?

      It's thrown by a subscript, not eq.
      perl -we '$x["y"]'
Re: File to array and reading back
by RichardK (Parson) on Jun 19, 2012 at 11:02 UTC

    As an alternative you could use either pairwise or each_array from List::MoreUtils

    I'd use each_array but YMMV