web-dev-qa-db-fra.com

Comment puis-je stocker des captures regex dans un tableau en Perl?

J'essaie d'utiliser regex en Perl. Je me demandais s'il était possible de stocker toutes les correspondances de l'expression dans un tableau? Je sais que je peux utiliser les éléments suivants: ($1,...,$n) = m/expr/g; mais il semble que cela ne peut être utilisé que si vous connaissez le nombre de correspondances que vous recherchez. J'ai essayé my @array = m/expr/g; mais cela ne semble pas fonctionner.

Merci de votre aide!

62
cskwrd

Si vous effectuez une correspondance globale (/g), alors l'expression régulière dans le contexte de la liste renverra toutes les correspondances capturées. Faites simplement:

my @matches = ( $str =~ /pa(tt)ern/g )

Cette commande par exemple:

Perl -le '@m = ( "foo12gfd2bgbg654" =~ /(\d+)/g ); print for @m'

Donne la sortie:

12
2
654
77
friedo

Voir l'entrée manuelle pour perldoc perlop sous "Correspondance dans le contexte de la liste":

Si l'option/g n'est pas utilisée, m // dans le contexte de la liste renvoie une liste composée des sous-expressions mises en correspondance par les parenthèses dans le modèle, c'est-à-dire ($ 1, $ 2, $ 3 ...)

Le modificateur/g spécifie la correspondance de modèle globale, c'est-à-dire la correspondance autant de fois que possible dans la chaîne. Son comportement dépend du contexte. Dans un contexte de liste, il renvoie une liste des sous-chaînes auxquelles correspondent toutes les parenthèses de capture dans l'expression régulière. S'il n'y a pas de parenthèses, il renvoie une liste de toutes les chaînes correspondantes, comme s'il y avait des parenthèses autour de l'ensemble du modèle.

Vous pouvez simplement récupérer toutes les correspondances en les affectant à un tableau ou en effectuant autrement l'évaluation dans le contexte de la liste:

my @matches = ($string =~ m/Word/g);
17
Ether

Parfois, vous devez obtenir toutes les correspondances dans le monde, comme le fait preg_match_all De PHP. Si c'est votre cas, vous pouvez écrire quelque chose comme:

# a dummy example
my $subject = 'Philip Fry Bender Rodriguez Turanga Leela';
my @matches;
Push @matches, [$1, $2] while $subject =~ /(\w+) (\w+)/g;

use Data::Dumper;
print Dumper(\@matches);

Il imprime

$VAR1 = [
          [
            'Philip',
            'Fry'
          ],
          [
            'Bender',
            'Rodriguez'
          ],
          [
            'Turanga',
            'Leela'
          ]
        ];
17
codeholic

Je pense que c'est un exemple explicite. Remarque /g modificateur dans le premier regex:

$string = "one two three four";

@res = $string =~ m/(\w+)/g;
print Dumper(@res); # @res = ("one", "two", "three", "four")

@res = $string =~ m/(\w+) (\w+)/;
print Dumper(@res); # @res = ("one", "two")

N'oubliez pas, vous devez vous assurer que la valeur l se trouve dans le contexte de la liste, ce qui signifie que vous devez entourer les valeurs scalaires entre parenthèses:

($one, $two) = $string =~ m/(\w+) (\w+)/;
8
Flimm

Notez que si vous connaissez le nombre de groupes de capture dont vous avez besoin per match, vous pouvez utiliser cette approche simple, que je présente à titre d'exemple (de 2 groupes de capture.)

Supposons que vous ayez des "données" comme

my $mess = <<'IS_YOURS';
Richard     Rich
April           May
Harmony             Ha\rm
Winter           Win
Faith     Hope
William         Will
Aurora     Dawn
Joy  
IS_YOURS

Avec l'expression régulière suivante

my $oven = qr'^(\w+)\h+(\w+)$'ma;  # skip the /a modifier if using Perl < 5.14

Je peux capturer les 12 (6 paires, pas 8 ... l'harmonie s'est échappée et la joie manque) dans le @box au dessous de.

my @box = $mess =~ m[$oven]g;

Si je veux "hacher" les détails de la boîte, je pourrais simplement le faire:

my %hash = @box;

Ou j'aurais juste pu sauter la boîte entièrement,

my %hash = $mess =~ m[$oven]g;

Notez que %hash contient les éléments suivants. L'ordre est perdu et les clés dupes (le cas échéant) sont écrasées:

(
          'April'   => 'May',
          'Richard' => 'Rich',
          'Winter'  => 'Win',
          'William' => 'Will', 
          'Faith'   => 'Hope',
          'Aurora'  => 'Dawn'
);
0
YenForYang