毎行、空行後か判定するよりは、ループを2つに分けた方が効率がいいと思うんだ。
好みによるだろうけど(´・ω・)

my (@head, @body);
while (<FH>) { push @head, $_; last if /^$/m; }
while (<FH>) { push @body, $_; }