my @matches = $string =~ /\b([a-z][a-z0-9_]+)/ig;
Si l'opération insensible à la casse ne doit être appliquée qu'à un sous-modèle, peut-on l'intégrer
/... \b((?i)[a-z][a-z0-9_]+) .../
(ou, il peut être désactivé après le sous-modèle, (?i)pattern(?-i)
)
Ce [a-zA-Z0-9_]
va comme \w
, a " caractère des mots "si c'est effectivement ce qu'il faut.
La regex ci-dessus sélectionne les mots comme il se doit sans qu'il soit nécessaire de couper la ligne sur un espace, ce qui est fait dans le programme illustré. On peut l'appliquer à la ligne entière (ou au texte entier), peut-être après avoir supprimé les divers caractères spéciaux. †
Il y a une question d'autres cas - pourquoi pas des traits d'union ? Des apostrophes ? Le tilde ? On ne les trouve pas dans les identificateurs, alors que le système semble destiné à traiter du texte de programmation, mais des commentaires sont inclus ; quels autres caractères légitimes peuvent-ils exister ?
Note sur divisé -sur les espaces blancs
L'exposition split / /, $line
se divise exactement sur cet espace. Le mieux est split /\s+/, $line
-- ou, mieux encore, d'utiliser split
Le modèle spécial de l'entreprise split ' ', $line
: divisé sur un nombre quelconque d'espaces blancs consécutifs, et où les espaces de début et de fin sont éliminés.
† L'exemple montré est correctement traité comme souhaité par la seule regex donnée.
use strict;
use warnings;
use feature 'say';
use Path::Tiny qw(path); # convenience, to slurp the file
my $fn = shift // die "Usage: $0 filename\n";
my @matches = sort map { lc }
path($fn)->slurp =~ /\b([a-z][a-z0-9_]+)/ig;
say for @matches;
J'ai ajouté le tri et la mise en minuscule pour correspondre à l'exemple de code dans la question, mais tout le traitement est effectué avec la regex indiquée sur le contenu du fichier dans une chaîne.
Le résultat est tel que souhaité (sauf que line
y world
ici viennent deux fois, ce qui est correct).
Notez que lc
peut être appliqué sur la chaîne de caractères avec le contenu du fichier, qui est ensuite traité avec la regex, ce qui est plus efficace. Bien que ce ne soit en principe pas la même chose dans ce cas, cela peut être
perl -MPath::Tiny -wE'$f = shift // die "Need filename\n";
@m = sort lc(path($f)->slurp) =~ /\b([a-z]\w+)/ig;
say for @m'
Ici, j'ai utilisé \w
. Ajustez le caractère réel pour qu'il corresponde, s'il est différent.