Ich springe recht spät auf den Zug auf. Das meiste ist ja schon geklärt, aber es gibt immer noch Kleinigkeiten:
2020-02-05T11:58:33
Raubtier
sub splitLineIntoWords {
my $line = shift;
$line = lc($line);
$line =~ s/[^[:alpha:]]/ /g;
return split ' ', $line;
}
- Die POSIX-Klasse [:alpha:] unterscheidet sich von Perls \w dadurch, dass der Unterstrich '_'nicht drin ist. Im normalen Sprachgebrauch gehört der Unterstrich zu den Sonderzeichen, und die ursprüngliche Lösung von Flips87 behandelt ihn auch so. Andererseits erwischt \w auch Buchstaben wie das "ö", das durchaus Bestandteil von Wörtern sein kann, aber es ist eben nicht in [:alpha:] enthalten. Ein s/[^[:alpha:]]/ /g; macht aus 'Wörtern' dann 'W rtern'.
- Das \w erfasst auch Zahlen. In der Original-Regex werden aus "3,1415" zwei Wörter "3" und "1415". Das kann Flips87 vermutlich beantworten, ob das so sein soll, wahrscheinlich ist es einfach unwichtig.
- Bei den Kleinbuchstaben vermute ich, dass es einfach darum geht, die Wörter unabhängig von Groß- und Kleinschreibung zu zählen. Dafür empfiehlt der Doktor inzwischen die Funktion fc (steht für "fold case"), die verlinkte Beschreibung erklärt die Hintergründe.
- Anstelle in der Zeile Ersetzungen durchzuführen und danach aufzuspalten, kann man auch in einem Aufwasch die Wörter aus dem String holen. Das hat rosti schon gezeigt - wäre da nicht die Sache mit dem Unterstrich und den Zahlen. Seit Perl 5.18 kann man auch das in einem Aufwasch erledigen, allerdings ist das Feature bis heute als "experimentell" gekennzeichnet, so dass man entweder eine Warnung in Kauf nehmen muss oder sie abstellen. Dann kann man Mengen-Operationen auf Zeichenklassen angeben, hier gezeigt als "alle Wort-Zeichen, aber keine Zahlen und nicht den Unterstrich" (siehe: perlrecharclass)
Damit hätten wir:
sub splitLineIntoWords {
my $line = fc shift;
no warnings "experimental::regex_sets";
$line =~ /(?[ \w - \d - [_] ])+/g;
}