When you undef $/; you'll read everything at once, so the while is not doing what I think you expect it to do.
I wrote the following example based on your regexp and slightly modified it to give the result that I believe are as expected.
use strict;
use warnings;
use Data::Dumper;
#my @array = <DATA>;
#my $text = join '', @array;
undef $/;
my $text = <DATA>;
my @matches = $text =~ m{class="report".*?&id=1">\s*(.*?)</a.*?"report
+"\swidth.*?>\s*(.*?)\s*</td>}sgx;
print Dumper(\@matches);
__DATA__
<td class="report">
<a href="blahblah1&id=1">link to blah 1</a>
</td>
<td class="report" width=50>
cell2 1
</td>
<td> some other stuff </td>
<td class="report">
<a href="blahblah2&id=1">link to blah 2</a>
</td>
<td class="report" width=50>
cell2 2
</td>
That outputs:
$VAR1 = [
'link to blah 1',
'cell2 1',
'link to blah 2',
'cell2 2'
];
Now you can iterate through the resulting array in pairs of two. Hope that helps.