Quelle est la différence entre $ / et $ ¢ en regex?


11

Comme le titre l'indique, quelle est la différence entre $/et ? Ils semblent avoir toujours la même valeur:

my $text = "Hello world";

$text ~~ /(\w+) { say $/.raku } (\w+)/;
$text ~~ /(\w+) { say $¢.raku } (\w+)/;

Les deux entraînent des objets Match avec les mêmes valeurs. Quelle est la logique d'utiliser l'un sur l'autre?

Réponses:


11

La variable $/fait référence à la correspondance la plus récente tandis que la variable fait référence à la correspondance la plus récente la plus externe. Dans la plupart des expressions rationnelles de base comme ci-dessus, cela peut être la même chose. Mais comme on peut le voir à la sortie de la .rakuméthode, les Matchobjets peuvent contenir d'autres Matchobjets (c'est ce que vous obtenez lorsque vous utilisez $<foo>ou $1pour les captures).

Supposons à la place que nous ayons le regex suivant avec une capture quantifiée

/ ab (cd { say $¢.from, " ", $¢.to } ) + /

Et couru, il verrait la sortie suivante si nous comparions avec "abcdcdcd":

0 2
0 4
0 6

Mais si nous passons de l'utilisation à $/, nous obtenons un résultat différent:

2 2
4 4
6 6

(La raison pour laquelle .tosemble être un peu décalée est qu'elle .pos- et - n'est pas mise à jour avant la fin du bloc de capture.)

En d'autres termes, fera toujours référence à ce qui sera votre objet de correspondance final (c'est-à-dire $final = $text ~~ $regex) afin que vous puissiez traverser un arbre de capture complexe à l'intérieur de l'expression régulière exactement comme vous le feriez après avoir terminé la correspondance complète. Ainsi, dans l'exemple ci-dessus, vous pouvez simplement faire $¢[0]pour se référer à la première correspondance, $¢[1]la seconde, etc.

À l'intérieur d'un bloc de code regex, $/fera référence à la correspondance la plus immédiate. Dans le cas ci-dessus, c'est la correspondance pour l'intérieur du ( )et ne connaîtra pas les autres correspondances, ni le début d'origine de la correspondance: juste le début du ( )bloc. Donnez donc une expression rationnelle plus complexe:

/ a $<foo>=(b $<bar>=(c)+ )+ d /

Nous pouvons accéder à tout moment en utilisant $ ¢ tous les foojetons en disant $¢<foo>. Nous pouvons accéder aux barjetons d'un donné fooen utilisant $¢<foo>[0]<bar>. Si nous insérons un bloc de code à l'intérieur de foola capture de, il pourra accéder aux barjetons en utilisant $<bar>ou $/<bar>, mais il ne pourra pas accéder à d'autres foos.


1
Ohhh! J'ai interprété le doc "La principale différence entre $/et est la portée: ce dernier n'a qu'une valeur à l'intérieur de l'expression régulière" pour signifier n'était qu'une trace résiduelle, tout comme Cursorc'est. Quand j'ai lu votre réponse, je pensais que ce serait le $*TOPje créé dans l' amélioration possible? section de ma réponse au SO "Pourquoi / comment une variable supplémentaire est-elle nécessaire pour faire correspondre le caractère arbitraire répété avec les groupes de capture?". Mais mes tentatives de remplacement $*TOPpar ont échoué. Comprenez-vous mon propos dans cette réponse? Pouvez-vous le faire fonctionner?
raiph

Raiph: Donc, dans les grammaires, est renouvelé pour chaque jeton, donc vous devriez dire $*TOP := $¢dans le TOPjeton mais cela ne supprime pas le besoin de $*TOPvar bien sûr. Je suis d'accord que ce serait génial de pouvoir faire référence à des matchs de haut niveau. Le problème est, en fin de compte, toujours celui que vous identifiez: lorsque la correspondance positionnelle / de hachage est publiée sur l'objet de correspondance. Lors de l'utilisation - qui est par jeton - les résultats seront par définition publiés dès que son { }bloc englobant sera rencontré.
user0721090601

Ce qui est intéressant pour moi, c'est qu'en développant Binex, je n'ai pas trouvé pire en termes de calcul de publier les résultats de match immédiatement après les avoir rencontrés. À la fin de la journée, vous poussez / sautez soit vers une liste / hachage mis en cache, soit vous poussez / sautez vers la liste / hachage du match. Cependant, il peut y avoir une sorte d'accélération interne que je ne connais pas utilisée pour LTM qui est probablement au cœur de celui-ci (le { }termine un jeton aux fins de LTM, et est donc plus susceptible d'être exécuté / testé que le reste du jeton dans un |regroupement)
user0721090601

Ahhh. J'avais sauté à la conclusion était dynamique, et j'ai été surpris quand cela n'a pas fonctionné. Mais le centime a maintenant laissé tomber qu'il est lexical, comme j'aurais pu le deviner compte tenu de votre utilisation du mot "le plus à l'extérieur", et est, comme vous l'expliquez, établi au début de chaque règle.
raiph

Ainsi, iiuc, au début d'une règle, un nouvel objet de correspondance est créé qui enregistre la position du curseur du moteur correspondant dans la chaîne d'entrée d'origine, mais est par ailleurs vide. (Droite?) Ensuite et $/sont liés au même objet, à savoir ce nouvel objet de correspondance, qui enregistrera ce que cette règle correspond et capture au fur et à mesure qu'elle progresse. Ensuite, au fur et à mesure que la correspondance progresse, il reste lié à cet objet de correspondance global, tandis qu'il $/est rebondi chaque fois qu'un nouvel objet de correspondance est créé, il correspond donc toujours, comme vous le dites, au dernier objet de correspondance. Droite?
raiph
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.