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 |
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) |
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) |
Code : | Sélectionner tout |
'\((.*)\)'