IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Python : ajouter des recherches en expressions régulières à sqlite3
Un billet de blog de tyrtamos

Le , par tyrtamos

0PARTAGES

Problématique

Le SGBDR sqlite3 qui vient avec Python ne comporte pas d'instruction permettant les recherches avec des expressions régulières. Il y a cependant des cas où on en a vraiment besoin. Comme c'est facile à ajouter, on va le faire!

Solution

On va ajouter 2 fonctions:
  • regexp(motif, item) qui va dire si oui on non l'item satisfait le motif
  • regextract(motif, item) qui va retourner la 1ère sous-chaine trouvée qui satisfait le motif, ou None s'il n'y en a pas.


Fonction regexp

Voilà la 1ère fonction. Il faut, bien sûr, importer le module re avant (=> import re):

Code PYTHON : Sélectionner tout
1
2
3
4
5
6
def regexp(motif, item): 
    """retourne True si le motif regex a été satisfait dans l'item 
       False sinon 
    """ 
    regex = re.compile(motif, re.I)  # re.I: ignore casse 
    return regex.search(item) is not None

On déclare cette fonction dans le pilote sqlite3 de Python comme suit (cnx est la variable de connexion à la base de données):

Code PYTHON : Sélectionner tout
cnx.create_function("REGEXP", 2, regexp)

Cette fonction, bien que non fournie par sqlite3, a cependant prévu une syntaxe particulière. Ainsi, au lieu d'utiliser une syntaxe comme "REGEXP(motif,item)", on va utiliser: "item REGEXP motif"!

Voilà un petit test:

Une table appelée "test" contient un champ "mots" qui contient:

Code : Sélectionner tout
1
2
3
4
5
aaa bbb ccc(ddd)eee fff 
aaa (bbb) ccc 
(aaa)bbb ccc ddd 
aaabbbcccddd(eee) 
aaabbbcccddd
On va chercher avec un script SQL les lignes qui contiennent des parenthèses ("cur" est ici un curseur):

Code PYTHON : Sélectionner tout
1
2
3
4
5
6
7
cur.execute(""" 
    SELECT mots 
    FROM test 
    WHERE mots REGEXP ? 
    ORDER BY mots 
    """, ('\(.*\)',)) 
liste = cur.fetchall()

Voilà ce que liste contient:

Code : Sélectionner tout
1
2
3
4
(aaa)bbb ccc ddd 
aaa (bbb) ccc 
aaa bbb ccc(ddd)eee fff 
aaabbbcccddd(eee)
On voit bien que l'item qui ne contient pas les parenthèses n'a pas été pris en compte.

Fonction regextract

Dans la liste précente qui contient au moins une fois des parenthèses, on va créer une 2ème fonction qui va en extraire son contenu.

Code PYTHON : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
def regextract(motif, item): 
    """retourne la 1ère sous-chaine qui satisfait au motif regex donné 
       si aucune sous-chaine n'est trouvée, renvoie None 
    """ 
    regex = re.compile(motif, re.I)  # re.I: ignore la casse 
    result = regex.findall(item)  # liste des sous-chaines trouvées 
    if result != []: 
        return result[0]  # on ne renvoie que la 1ère s'il y en a plusieurs 
    else: 
        return None

Application:

Code PYTHON : Sélectionner tout
1
2
3
4
5
6
7
cur.execute(""" 
    SELECT regextract(?,mots) as parentheses 
    FROM test 
    WHERE mots REGEXP ? 
    ORDER BY parentheses 
    """, ('\(.*\)', '\(.*\)')) 
liste = cur.fetchall()

Et cette fois le résultat sera:

Code : Sélectionner tout
1
2
3
4
(aaa) 
(bbb) 
(ddd) 
(eee)
Bien sûr, on pourrait ne prendre que le contenu des parenthèses sans celles-ci: il suffit de modifier un peu le motif:

Code : Sélectionner tout
 '\((.*)\)'
.

Une erreur dans cette actualité ? Signalez-nous-la !