Du kannst doch erst nach \n splitten danach wieder nach \t. scalar @values sagt Dir dann wie viele Felder mit mit \t getrennt waren.
foreach my $zeile ( split/\n/, $rec_db ) {
my @values = split /\t/, $zeile;
# und dann hast Du die Werte alle im Array
# um sie über Ihren Namen anzusprechen gäng's auch so
my @keys = qw/nr keyword titel meta-keywords meta-desc meta-page-topic datei(Pfad)/;
my %hash = map {length $values[$_] ? ($key[$_] => $values[$_]) : ()} 0..$#values if scalar @values;
# nun kannst Du z.B. mit exists $hash{nr} nachschauen,
# ob die gewünschten Werte existierten,
# denn die Schlüssel werden nicht angelegt,
# wenn zwei \t aufeinander folgten
# oder wenn nicht alle Felder angegeben wurden.
# ansonsten gänge auch @hash{@keys} = @values;
}
In Deinem regulären Ausdruck [\w* ] ist * kein Wiederholungsfaktor, sondern es ist durch die [] eine Zeichenklasse mit dem Inhalt \w, * und Leerzeichen, es hätte vielleicht [\w ]* heißen sollen.
Mit der Zeile
$zeile =~ s/\|/\t/g;
machst Du | gleichwertig zu \t.
Dann kannst Du aber auch gleich
my @values = split /[\t|]/, $zeile;
oder
my @values = split /\t|\|/, $zeile;
schreiben.
Willst Du auch noch Leerzeichen links und rechts eben dem Seperator \t oder | zulassen, geht dann auch:
my @values = split / *[\t|] */, $zeile;\n\n
<!--EDIT|steffenw|1072786878-->
$SIG{USER} = sub {love 'Perl' or die};