2010-12-03 8 views
4

Je cherche une expression régulière qui va correspondre à n'importe quel nombre de 1 à 50 inclusivement. Jusqu'à présent, j'ai trouvé des exemples mais tous permettent à la chaîne de contenir un point décimal, que je ne veux pas inclure. Donc 1,13,24,50 sont OK mais 1., etc. ne le sont pas. Y a-t-il un REGEXP que je peux utiliser?Expression régulière pour 1-50 sans point décimal

Merci à l'avance, Tim

Répondre

6

Essayez ceci:

/^(?:[1-9]|[1-4][0-9]|50)$/ 

MISE À JOUR:

Maintenant que je vois la question a été mis à jour pour faire référence à MySQL, cela change considérablement les choses. L'expression régulière mentionnée ci-dessus utilise des parens non-capturantes qui ne sont pas supportées par MySQL. Mais cela soulève aussi la question. devriez-vous vraiment utiliser des expressions régulières pour résoudre ce problème? Nous devons vraiment regarder comment vous stockez vos chiffres qui doivent être entre 1 et 50. Sont-ils varchar s? Sont-ils int s? Je vais montrer comment le résoudre dans les deux sens. D'abord, je vais mettre en place une table de test avec des index:

create table regextest (
    id int unsigned primary key auto_increment, 
    varchar_number varchar(5) not null, 
    int_number int not null, 
    index(varchar_number), 
    index(int_number) 
) engine=innodb; 

Maintenant mettre des données de test dans ce fait que tous nos cas de bord sont couverts:

insert into regextest (varchar_number, int_number) 
    values ('0', 0), ('1', 1), ('35', 35), ('49', 49), ('50', 50), ('51', 51); 

Et maintenant, voici une requête résoudra votre problème en supposant que vos numéros sont stockés sous forme de chaînes dans la colonne varchar_number:

mysql> select * from regextest where varchar_number rlike '^([1-9]|[1-4][0-9]|50)$'; 
+----+----------------+------------+ 
| id | varchar_number | int_number | 
+----+----------------+------------+ 
| 2 | 1    |   1 | 
| 3 | 35    |   35 | 
| 4 | 49    |   49 | 
| 5 | 50    |   50 | 
+----+----------------+------------+ 
4 rows in set (0.00 sec) 

Cela fonctionne, mais il fonctionnera mal sur de grands ensembles de données, car il ne peut pas u se un index même si l'un est présent. MySQL doit exécuter l'expression régulière une fois pour chaque ligne de la table. Supposons que vos numéros compris entre 1 et 50 ont été stockés sous la forme int dans la colonne int_number. Vous pouvez simplement faire ceci:

mysql> select * from regextest where int_number between 1 and 50; 
+----+----------------+------------+ 
| id | varchar_number | int_number | 
+----+----------------+------------+ 
| 2 | 1    |   1 | 
| 3 | 35    |   35 | 
| 4 | 49    |   49 | 
| 5 | 50    |   50 | 
+----+----------------+------------+ 
4 rows in set (0.00 sec) 

Cette requête fonctionnera bien car elle peut utiliser un index et elle est aussi plus lisible et plus facile à maintenir. Gagne tout autour.

+0

Salut, merci pour votre commentaire. J'essaie ce qui suit dans MySQL: Sélectionnez 1 REGEXP '/^(?: [1-9] | [1-4] [0-9] | 50) $ /' mais il arrive avec l'erreur: Erreur ' opérande de répétition-opérateur invalide 'de regexp. J'ai vu que cela pourrait être dû à ne pas échapper à un backslash, et j'ai essayé de faire // au lieu de/mais ne fonctionnait toujours pas ... Des idées? – Tim

+0

@Tim: Le problème est probablement la syntaxe '(?: ...)', qui introduit un groupe non-capturant. Il semble que MySQL ne supporte pas cela, et essaie de traiter '?' Comme un opérateur de répétition, bien que cela n'ait rien à répéter. Si vous remplacez '(?: ...)' par des parenthèses ordinaires '(...)', cela devrait fonctionner. –

+0

Merci, j'ai essayé mais/^ (([1-9] | [1-4] [0-9] | 50) $ /) mais il ne correspond pas aux chiffres corrects. – Tim

4
'^(0?\d|[1-4]\d|50)$' 

qui est:

  • Le début de l'entrée
  • suivie, ou
  • par un seul chiffre (en option précédée d'un 0) suivi d'un 1-4 suivi d'un chiffre, ou
  • suivi par 50
  • puis assurez-vous que nous voyons la fin de l'entrée.

Edit: Le 0 ci-dessus permet (et 00) que vous ne voulez pas sûrement. Donc, en admettant que vous ne l'avez pas vraiment envie des zéros à gauche autorisé de toute façon:

'^([1-9]|[1-4]\d|50)$' 

Edit: Comme commentaires plus tard de l'OP indiquent que ceci est pour MySQL, j'ai changé la syntaxe pour spécifier le motif.

+2

Cela correspond à '0 'ce qui n'est pas autorisé. – Asaph

+0

@ Asaph Vous avez raison! Merci; J'ai modifié pour montrer le correctif. – Phrogz

+0

Merci ... MySQL donne la même erreur non répétitive que celle mentionnée ci-dessus ... – Tim

1

^([1-9] | [1-4] [0-9] | 50) $

+0

1 à 9 OU 10 à 49 OU 50 –

+0

Merci. Cependant, cela permet par exemple 1. – Tim

+0

@Tim Si votre commentaire ci-dessus signifie "il permet' 1.' ", alors vous avez tort: ​​il ne permet pas un point. Si votre commentaire signifie "il permet' 1' ", alors c'est ce que vous avez déclaré explicitement qu'il devrait correspondre. Le motif ci-dessus me semble bien. – Phrogz

0

"Tricherie" avec Perl6::Rules:

/ (\d+) { 1 <= $1 && $1 <= 50 or fail }/

ou en Perl 5.10 et plus,

/(\d+)(?(?{1>$1||50<$1})(*FAIL))/ 
+0

Ou en Perl5: '/^(\ d +) $ (? (? {1> $ 1 || 50 <$ 1}) (* FAIL))/x' – tchrist

+0

@tchrist: Merci, mis à jour. – ephemient

0

essayez celui-ci

([0-4]{1}[0-9]{0,1}[.]{0,1}[0-9]{0,2}|50) 

fera-t-Fo

45.00 - Match 
4  - Match 
78 - Not Match 
51 - Not Match 
21.25 - Match 
+0

Trois problèmes: (1) Le PO a déclaré qu'il * ne voulait pas * faire correspondre les points décimaux. (2) Il a également dit que le nombre ne peut pas être '0' ou' 00': votre regex correspond aux deux. (3) Vos quantificateurs ont besoin de travail; '{0,2}' est correct, mais '{0,1}' devrait être écrit comme '?', Et '{1}' devrait être supprimé. Tout ce qu'il fait est de dire au moteur regex de faire ce qu'il allait faire de toute façon: correspondre exactement à l'un des atomes auquel il est attaché. –

Questions connexes