J'ai cet exemple de code
dear.{0,6}(brother|friend)
$ 1 affichera la correspondance qui est "Cher frère". Existe-t-il un moyen d'obtenir la regepx complète qui correspond à cette chaîne?
Dans ce cas
#!/usr/bin/perl
use strict;
use warnings;
my $string = "Dear Brother,fgfgfg Test Test2 Soon trthggh";
if ($string =~ /(expr1|expr2|dear.{0,6}(brother|friend)|Soon)/i){print "$1";}
C'est possible de le faire?
3 Réponses :
J'ai cette solution fonctionnelle. Mais sur trop d'expressions, je pense que la boucle peut ralentir le script. D'autres idées plus intéressantes sont les bienvenues, mais arrêtez de me parler de $ 1 ou $ &.
#!/usr/bin/perl
use strict;
use warnings;
my $string = "Dear Brother, fgfgfg Test Test2 Soon trthggh";
my $regexstring = "expr1|expr2|dear.{0,6}(brother|friend)|Soon|out.php\?s=(7644|4206|6571|4205)";
my @regexarray = ("expr1", "expr2", "dear.{0,6}(brother|friend)", "Soon", "out.php\?s=(7644|4206|6571|4205)");
if ($string =~ /($regexstring)/i){
my $match = $1;
for my $expr (@regexarray){
print "$expr\n" if ($match =~ /($expr)/i);
}
}
Pourquoi ne pas créer la regexstring à partir du regexarray et ajouter des captures nommées dans la même exécution? my $ i = 0; my $ regexstring = join "|", map {qr / (? <$ i ++> $ _) /} @regexarray; if ($ string = ~ / $ regexstring /) {print @regexstring [clés% +]}
Si vous créez de toute façon l'expression régulière en utilisant un programme, il est facile d'injecter les séquences (? <...>) appropriées et de regarder ensuite laquelle (s) correspond (s) par la suite. Adapter le programme que vous avez posté en tant que première tentative:
Found <Dear Brother>
Matched via group_2 => Dear Brother
Matched via /(?^i:dear.{0,6}(brother|friend))/
J'ai changé les chaînes en expressions régulières ci-dessus pour faciliter les guillemets et l'insensibilité à la casse.
#!/usr/bin/perl
use strict;
use warnings;
my $string = "Dear Brother, fgfgfg Test Test2 Soon trthggh";
my @regexarray = (qr/expr1/, qr/expr2/, qr/dear.{0,6}(brother|friend)/i, qr/Soon/, qr/out.php\?s=(7644|4206|6571|4205)/);
my $i= 0;
my $regexstring = join "|", map {
my $groupname= sprintf 'group_%d', $i++;
qr/(?<$groupname>$_)/i
} @regexarray;
if ($string =~ /($regexstring)/i){
my $match = $1;
print "Found <$1>\n";
print "Matched via ";
(my $found) = keys %+;
print "$found => $+{$found}\n" for keys %+;
$found =~ /(\d+)$/
or die "Invalid group name '$found'";
my $index = $1;
print "Matched via /$regexarray[ $index ]/\n";
}
Vous pourriez peut-être utiliser cette approche:
my $part2 = "(brother|friend)";
my $part1 = "(expr1|expr2|dear.{0,6}$part2|Soon)";
my $string = "Dear Brother,fgfgfg Test Test2 Soon trthggh";
if ($string =~ /$part1/i){print "$part1";}
Je ne connais plus de méthode automatisée. Peut-être que vous devez pirater un moteur d'expression régulière, sans utiliser directement Perl.
Je ne veux pas de 1 $! J'ai besoin d'un moyen d'obtenir l'expression complète qui correspond à la chaîne.
Peut-être
if (/ (expr1) /) {vous savez que c'est expr1} ... elsif (/ (cher ...) /) {c'est ce re}, ce qui signifie remplacer le| < / code> s avec un groupe deifsCette approche conditionnelle pour chaque regex n'est pas possible. J'ai des centaines d'expressions régulières pour les comparer.
Je l'ai trouvé ... Backreference nommé. Corion, pouvez-vous donner quelques exemples car perldoc est très pauvre.
Si ma réponse a fonctionné pour vous, pouvez-vous l'accepter? stackoverflow.com/help/someone-answers