2009-04-11 5 views
5

Je suis confus par les docs:Pourquoi % () est-il plus rapide que () dans Vim?

\%(\) Un motif entouré par échappées entre parenthèses. */\%(\)* */\%(**E53* Tout comme \(\), mais sans compter comme sous-expression. Cela permet en utilisant plus de groupes et c'est un peu peu plus rapide.

Quelqu'un peut-il expliquer la raison de la différence? Est-ce à cause d'un retour en arrière ou d'autre chose?

Répondre

11

Le commentaire «un peu plus rapide» est précis dans la mesure où il y a un peu moins de comptabilité à faire, mais l'accent est mis sur «un peu» plutôt que «plus rapide». Fondamentalement, normalement, le matériau correspondant à \(pattern\) doit être conservé afin que vous puissiez utiliser \3 (pour le nombre approprié) pour s'y référer dans le remplacement. La notation % signifie que vim n'a pas besoin de garder une trace de la correspondance - donc il fait un peu moins de travail.


@SimpleQuestions demande:

Que voulez-vous dire par "garder une trace du match"? Comment affecte-t-il la vitesse?

Vous pouvez utiliser des parenthèses échappées pour «capturer» des parties du motif correspondant. Par exemple, supposons que nous jouons avec des déclarations de fonctions simples C - pas de pointeurs vers des fonctions ou d'autres sources de parenthèses - alors nous pourrions avoir une commande de substitution, comme les suivantes:

[email protected]\<\([a-zA-Z_][a-zA-Z_0-9]*\)(\([^)]*\))@xyz_\1(int nargs) /* \2 */@ 

Compte tenu d'une ligne d'entrée tels que:

int simple_function(int a, char *b, double c) 

la sortie sera:

int xyz_simple_function(int nargs) /* int a, char *b, double c */ 

(Pourquoi pourriez-vous faire que je me fais que je dois envelopper la fonction C simple_function de sorte qu'il peut être appelé à partir d'un langage compilé en C qui utilise une convention d'interface différente - il est basé sur Informix 4GL, pour être précis. Je l'utilise pour obtenir un exemple - pas parce que vous avez vraiment besoin de savoir pourquoi c'était un bon changement à faire.)

Maintenant, dans l'exemple, les \1 et \2 dans le texte de remplacement se réfèrent aux pièces capturées. de l'expression régulière - le nom de la fonction (une séquence d'alphanumériques commençant par un caractère alphabétique - soulignant le comptage comme 'alphabétique') et la liste des arguments de fonction (tout entre les parenthèses, mais n'incluant pas les parenthèses).

Si j'avais utilisé la notation \%(....\) autour de l'identificateur de la fonction, alors \1 se référerait à la liste des arguments et il n'y aurait pas \2. Parce que vim n'aurait pas besoin de garder une trace de l'une des deux parties capturées de l'expression régulière, il a légèrement moins de comptabilité à faire que s'il devait garder une trace de deux parties capturées. Mais, comme je l'ai dit, la différence est minime; vous ne pourriez probablement jamais le mesurer en pratique.C'est pourquoi le manuel dit «ça permet plus de groupes»; Si vous aviez besoin de regrouper des parties de votre expression régulière mais que vous n'aviez pas besoin de vous y référer à nouveau, vous pourriez travailler avec des expressions régulières plus longues. Cependant, au moment où vous avez plus de 9 parties mémorisées (capturées) à l'expression régulière, votre cerveau fait généralement des girations et vos doigts feront des erreurs de toute façon - donc l'effort n'en vaut généralement pas la peine. Mais c'est, je pense, l'argument pour utiliser la notation \%(...\). Il correspond à la notation Perl (PCRE) '(?:...)' pour une expression régulière non-capturante.

+0

Que voulez-vous dire par "garder la trace de la correspondance"? Comment affecte-t-il la vitesse? –

+0

J'ai effectivement vérifié - et cela fonctionne comme indiqué. Et j'ai vérifié la version de \% (\\) - non montrée ci-dessus - et cela a fonctionné aussi. Phew! Cela n'arrive pas à chaque fois que tout fonctionne correctement. J'étais confiant du concept ... mais c'est toujours une bonne idée de vérifier la réalité. –

4

J'ai demandé dans #Vim, si l'autre est plus rapide en raison de retour en arrière. Le godlygeek utilisateur a répondu:

Non, il est plus rapide parce que la chose qui correspond n'a pas besoin d'être strdup'ed - tout travail inutile est une mauvaise chose pour un fichier de syntaxe.

Il a continué:

[La vitesse] dépend de la taille de la chaîne est . Pour 3 caractères, il n'a pas beaucoup d'importance, pour 3000 il le fait probablement. Et gardez à l'esprit que il doit être strdup'ed chaque fois qu'il correspond .... y compris pendant retour arrière ... ce qui signifie que même les 3 caractères pourraient être strdup'ed 1000 fois au cours de l'appariement une seule regex. - les fichiers de syntaxe sont dans $ VIMRUNTIME/syntax

Questions connexes