7
votes

Ordre alphabétique Regex à l'aide de backreferences

J'ai récemment rencontré un puzzle pour trouver une expression régulière qui correspond:

Cordes de 5 caractères à 5 caractères constituées de lettres anglaises minuscules en ordre croissant ASCII Command

Des exemples valides incluent: xxx

exemples non valides incluent: xxx

Ma solution actuelle est kludgie . J'utilise la regex: xxx

qui utilise un groupe de capture non consommant pour affirmer une longueur de chaîne de 5, puis vérifie que la chaîne comprend des lettres anglaises minuscules dans l'ordre ( voir Rubular ).

à la place, j'aimerais utiliser des références arrière à l'intérieur du caractère Des classes. Quelque chose comme: xxx

la logique de la solution ( voir rubular < / a>) Dans ma tête consiste à capturer le premier caractère [AZ], utilisez-le comme une brouillon dans la deuxième classe de caractères et ainsi de suite. Cependant, \ 1 , \ 2 ... dans les classes de caractères semblent se référer aux valeurs ASCII de 1, 2 ... correspondant efficacement à une chaîne de quatre ou cinq caractères .

J'ai 2 questions:

  1. Puis-je utiliser des références arrière dans mes classes de caractères pour vérifier les chaînes d'ordre croissant?
  2. Y a-t-il une solution moins de hacky à ce casse-tête?

9 commentaires

Pour autant que je sache, votre solution de kludgie est aussi douce que possible parce que les classes de personnages ne jouent pas bien avec votre courte retour (mais je ressemble à votre logique, semble être une bonne fonctionnalité). Avez-vous un environnement spécifique pour exécuter cette regex dans (rubis seulement ou agnostique)? Je suis convaincu que les sorciers de regex de SO vont-ils subir prochainement pour ajouter leur expertise.


Euh, pas de retour de retour dans les classes de caractères. La raison en est que les classes de caractères sont composées à Compilation Time . Le facteur déterminant est qu'une brouillon est dynamique et ce qui la disqualifie à l'intérieur d'une classe est l'opérateur de gamme. Donc, ils disent .. aucune plage dynamique ELST Le moteur se bloque dans une exception C ++.


est tombé sur un puzzle pour trouver une expression régulière - Assurez-vous de CITE Ce lien afin que nous puissions rire de la puzzler ..


En fait, c'est assez facile dans une regex Perl. Vous pouvez faire toutes sortes de choses, comme le comptage, les séquences, les bools, la soustraction, etc. (? {..}) . Si vous pensez utiliser Perl, alors c'est .. faisable. BTW, votre première regex est tout à fait bien.


Une autre chose à noter est que dans les classes de caractères, l'opérateur gamme concerne des caractères unique (min, max) et non un ensemble de caractères, comme \ pl-z jette une construction Erreur. Dans cette veine, une référence peut contenir plusieurs caractères.


Pourquoi démos inclus dans la liste non valide?


Ok, votre regex a l'air assez gentil avec moi. Vous pouvez l'améliorer légèrement en utilisant: ^ (? = [AZ] {5} $) A * B * C * D * E * F * G * H * I * J * K * L * M * N * o * p * q * r * s * t * u * v * w * x * y * z * $


Dupliquer de https://stackoverflow.com/questions/3171671/regex-5-Digits- I-croissant-commande


La question ne peut pas être fermée en raison de la prime, mais c'est une liaison de dupe morte-sur-lepe.


4 Réponses :


4
votes

Je pose cette réponse plus comme un commentaire qu'une réponse puisqu'il a une meilleure mise en forme que des commentaires.

liée à vos questions:

  1. Puis-je utiliser des références arrière dans mes classes de caractères pour vérifier les chaînes d'ordre croissant?

    Non, vous ne pouvez pas. Si vous regardez un look un Section Régulière de Backdref , vous trouverez ci-dessous la documentation:

    parenthèses et arrière-plan ne peuvent pas être utilisés dans des classes de caractères

    Les parenthèses ne peuvent pas être utilisées dans des classes de caractères, du moins pas comme des métacaractères. Lorsque vous mettez une parenthèse dans une classe de caractères, elle est traitée comme un caractère littéral. Donc, la regex [(a) b] correspond à A, B, (et).

    Backreferences, aussi, ne peut pas être utilisé à l'intérieur d'une classe de caractères . Le \ 1 dans une regex comme (a) [\ 1b] est une erreur ou un littéral 1

    En ce qui concerne votre 2e question:

    1. Y a-t-il une solution moins de hacky à ce casse-tête?

      IMHO, votre regex est parfaitement bien, vous pouvez la raccourcir très peu au début comme celui-ci: xxx

      Regex Demo


2 commentaires

Je pense que ça vaut la peine de dire pourquoi Les rafraîchissements dans des classes de caractères ne sont pas possibles. Une anti-perfection peut indiquer une sous-chaîne assortie, qui pourrait être n'importe quelle longueur, même vide. Ainsi, le code comme [\ 1-z] pourrait produire [- z] , [fz] , [foo-z] etc. qui n'a pas beaucoup de sens et que le motif devrait être recompilé à la volée, empêchant ainsi les optimisations.


Il est dérangeant de voir les documents cités lorsqu'ils ne fournissent pas de raisons pour des raisons si quelque chose ne peut pas être utilisé de manière aussi fondamentale. Les références à l'intérieur des classes de caractères sont un exemple. Mais vous pouvez toujours utiliser votre propre raisonnement pour un tel cas, et il est assez facile de savoir pourquoi dans ce cas.



3
votes

Si vous êtes prêt à utiliser Perl (!), cela fonctionnera:

/^([a-z])((??{"[$1-z]"}))((??{"[$2-z]"}))((??{"[$3-z]"}))(??{"[$4-z]"})$/


2 commentaires

Mais ... ça triche! :) Si vous utilisez Perl, je suppose que vous pourriez simplement coder l'affirmation directement: / ^ ([[[AZ] {5}) $ (? (? {$ 1 EQ (JOINT ", Sort SPLIT QR ##, $ 1 )}) | (?!)) /


À un moment donné, je pense qu'il est douteux de savoir si vous faites une solution de regex. Je pense que le mien est plus proche du continuum :)



2
votes

Puisque quelqu'un a cassé la glace en utilisant perl, c'est un
Solution Perl, je suppose ..


Notez qu'il s'agit d'une solution de base non dégophale qui arrive à être bourré dans des constructions de code à l'intérieur d'une plus grande réégalité de Perl.
La chose intéressante est que si une journée vient quand vous avez besoin de la synergie
de regex / code c'est un bon choix.
Il est alors possible qu'au lieu d'un simple [A-Z] code>, vous pouvez
Utilisez un motif très complexe de sa place et d'utiliser un chèque par rapport au dernier.
C'est la puissance !! / em> p>


la regex ^ (?: ([[Az]) (? (? {$ Dernier GT $ 1}) (?!) | ( ? {$ last = 1}))) {5} $ code> p>

code PERL p> xxx pré>

good   aaaaa
good   abcde
good   xxyyz
good   ghost
good   chips
good   demos
bad    abCde
bad    xxyyzz
bad    hgost
bad    chps


0 commentaires

2
votes

Ah, eh bien, c'est un ensemble fini, vous pouvez donc toujours l'énumérer avec une alternance! Cela émet une sorte de «force brute» de regex dans un petit Perl repl: xxx

et maintenant: xxx

la regex est seulement 220 Ko ou tellement; -)


3 commentaires

Aargh. Votre regex a cassé rubrique (ne peut pas faire un permalink). :-) Oui, c'est 219 KB RAW et fonctionne!


Merci pour cela. Utilisation du texte brut de regex (de @Jedi Coller bin), je l'ai mis via ce Outil ternaire et a fait une trie complète de regex soufflé. Qui a réduit la taille un peu (160k compressé , 840k formaté ). Voici un Test Python .


En outre, j'ai généré les chaînes complètes de 142 506 possibles, puis utilisée la TRIE REGEX complète que j'ai faite pour tester les performances: REGEX1: Options: Terminé Itérations: 1/1 (x 1) Correspondances trouvées par itération : 142506 Temps écoulé: 0,18 s, 178,87 ms, 178871 μs