Outils pour utilisateurs

Outils du site


divers_expr_reg

Expressions régulières diverses

Vous trouverez ici quelques expressions régulières avec leur “décodage” en langage humain (et ce n'est pas du luxe :-D).

test d'un nombre entier

motif = r"^[+-]?[0-9]+$"

avec:

^      -> on commence au début de la chaine
[+-]?   -> éventuellement un"+" ou un "-"
[0-9]+   -> un ou plusieurs chiffre(s)
$   -> on termine à la fin de la chaine

Bien sûr, si on veut chercher un entier dans une chaine qui contient aussi autre chose, il faut retirer les “^” et “$”.

A noter que le motif trouve aussi un nombre entier très long (comme “5555555555555555555555” par exemple) qui n'est pas un “int” en Python, mais un “long”.

test d'un nombre réel (ou flottant, ou à "virgule flottante")

motif = r"^[+-]?(([0-9]+[eE][+-]?[0-9]+)|([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)|(\.[0-9]+([eE][+-]?[0-9]+)?))$"

avec:

^
[+-]?     il peut y avoir ou pas un signe
(
([0-9]+[eE][+-]?[0-9]+)     si le 1er nb est entier (un ou plusieurs chiffres), alors, l'exposant est obligatoire
|
([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)   si le 1er nombre (un ou plusieurs chiffre(s)) est suivi d'un point, alors les chiffres suivants et l'exposant sont optionnels 
|
(\.[0-9]+([eE][+-]?[0-9]+)?) si on commence par un point, il y a un ou plusieurs chiffre(s) derrière, et l'exposant est optionnel
)
$

Bien sûr, si on veut chercher un tel nombre (entier ou réel) dans une chaine qui contient aussi autre chose, il faut retirer les “^” et “$”.

A noter qu'on peut faire plus court, (mais encore moins clair!) en remplaçant “[0-9]” par “\d”, ce qui donne:

motif = r"^[+-]?((\d+[eE][+-]?\d+)|(\d+\.\d*([eE][+-]?\d+)?)|(\.\d+([eE][+-]?\d+)?))$"

On pourrait aussi mettre le motif de l'exposant en facteur dans les 2 derniers cas, mais cela conduirait à ajouter des parenthèses imbriquées.

Vous pouvez essayer et éventuellement modifier l'expression régulière comme vous voulez avec la boucle suivante:

motif = r"^[+-]?(([0-9]+[eE][+-]?[0-9]+)|([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)|(\.[0-9]+([eE][+-]?[0-9]+)?))$"
while True:
    x = raw_input("x = ").strip()
    if x == "":
        break
    if re.match(motif, x):
        print u"x est un réel"
    else:
        print u"x n'est pas un réel"

test d'un nombre quelconque (entier ou réel)

On peut simplement ajouter l'option supplémentaire “est entier” à la précédente, ce qui devient:

motif = r"^[+-]?(([0-9]+)|([0-9]+[eE][+-]?[0-9]+)|([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)|(\.[0-9]+([eE][+-]?[0-9]+)?))$"

Et ce qui se lit:

^
[+-]?     il peut y avoir ou pas un signe
(
([0-9]+)  ça pourrait être un nombre entier
|
([0-9]+[eE][+-]?[0-9]+)     il pourrait y avoir un nombre entier suivi d'un exposant
|
([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)   si le 1er nombre (un ou plusieurs chiffre(s)) est suivi d'un point, alors les chiffres suivants et l'exposant sont optionnels 
|
(\.[0-9]+([eE][+-]?[0-9]+)?) si on commence par un point, il y a un ou plusieurs chiffre(s) derrière, et l'exposant est optionnel
)
$

Mais, en fait, l'expression se simplifie, ce qui donne:

motif = r"^[+-]?((([0-9]+(\.[0-9]*)?)|(\.[0-9]+))([eE][+-]?[0-9]+)?)$"

Sa lecture est plus complexe, et on peut mieux la comprendre avec l'indentation:

^
[+-]?   éventuellement un signe
(
    (
        ([0-9]+(\.[0-9]*)?)  on commence par un chiffre, éventuellement suivi d'un point, lui-même éventuellement suivi d'un ou plusieurs chiffres ("1." est accepté en tant que "1.0")
        |
        (\.[0-9]+)    on commence par un point, suivi d'un ou plusieurs chiffre(s) (".1" est accepté en tant que "0.1", mais, bien sûr, "." est refusé)
    )
    ([eE][+-]?[0-9]+)?   et dans l'un ou l'autre des 2 cas précédents, on peut avoir éventuellement un exposant 
)
$

L'avantage d'utiliser les expressions régulières est ici évidente:

  • si je veux limiter mes nombres à des nombres entiers ou réels mais sans exposant, il suffit de supprimer le motif de l'exposant
  • si en plus je veux reconnaître des nombres écrits en français (avec la virgule), il suffit que je remplace le point par une virgule dans le motif.


Et voilà une fonction qui, à partir d'une chaine, renvoie un entier, un entier long, un flottant ou False (d'après une idée de eyquem: http://www.developpez.net/forums/d656901/autres-langages/python-zope/general-python/verifier-entree-nombre/).

def numbereval(x):
    if re.match(r"^[+-]?[0-9]+[lL]?$", x):
        if x!="" and x[-1] in "lL":
            return long(x[:-1])
        else:
            return int(x)
    elif re.match(r"^[+-]?(([0-9]+[eE][+-]?[0-9]+)|([0-9]+\.[0-9]*([eE][+-]?[0-9]+)?)|(\.[0-9]+([eE][+-]?[0-9]+)?))$", x):
        return float(x)
    else:
        return False

Cette fonction détecte un entier long de 2 façon différentes:

  • si l'entier est tellement long qu'il déborde le “int” (exemple: “55555555555555555555”).
  • si l'entier est donné avec un “l” ou un “L” à la fin (exemple: “12L”).

Et voilà le code pour le tester:

while True:
    y = numbereval(raw_input('x =').strip())
    if y:
        print type(y), y
    else:
        print u"ce n'est pas un nombre"


Amusez-vous bien!

divers_expr_reg.txt · Dernière modification: 2008/12/11 18:37 par tyrtamos

Outils de la page