2
votes

Perl: afficher regex, pas de correspondance

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?


5 commentaires

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 de if s


Cette 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


3 Réponses :


2
votes

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);
    }
}


1 commentaires

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% +]}



5
votes

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.

Résultat h3 >
#!/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";
}


0 commentaires

-1
votes

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.


0 commentaires