J'ai trouve ma regex mais ça fonctionne pas !

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjour, j'ai trouvé une regex pour pouvoir identifier toute les phrases d'un fichier dans le but d'en écrire une par ligne après un nettoyage (il y a des sauts de lignes au milieu des phrases).

J'utilise cette regex :

1
reg = "[^.?!]*[.?!]$"

J'ai testé sur ce site et ça marche très bien. Sauf que quand j'utilise les lib de python ou lua rien n'est trouvé… Auriez vous une idée ?

+0 -0

Sauf que quand j'utilise les lib de python ou lua rien n'est trouvé… Auriez vous une idée ?

Ricocotam

De quelle manière t'y prends-tu en Python ? Car je n'ai personnellement aucun problème avec ton expression rationnelle.

1
2
3
>>> reg = re.compile('[^.?!]*[.?!]$')
>>> reg.match('Bonjour !')
<_sre.SRE_Match object; span=(0, 9), match='Bonjour !'>

J'utilise cette regex :

1
reg = "[^.?!]*[.?!]$"

J'ai testé sur ce site et ça marche très bien. Sauf que quand j'utilise les lib de python ou lua rien n'est trouvé… Auriez vous une idée ?

Ricocotam

A quoi sert le '$' final ?

Sinon, en python, tu peux faire plus simple :

1
re.split('[.?!]', string)
+0 -0

Un $ signale qu'on veut la fin de l'input (ou de la ligne si on utilise un flag qui traite chaque ligne comme input). Il y a ^ pour le début.

It goes against the grain of modern education to teach children to program. What fun is there in making plans, acquiring discipline in organizing thoughts, devoting attention to detail and learning to be self-critical? – Perlis

+0 -0
Auteur du sujet

Merci de tout vos retours ! Visiblement c'est le '$' qui était gênant je l'ai donc enlevé et ça fonctionne. Par contre j'ai un problème c'est que dans mon texte (les misérables) j'ai des abréviations comme 'M.' ou 'B.' mais aussi 'Mme' et je n'arrive pas à avoir ce que je veux ^^. Voici un exemple :

1
2
En 1804, M. Myriel était curé de B. (Brignolles). Il
était déjà vieux, et vivait dans une retraite profonde.

Donne :

1
2
3
4
5
# 1 :
En 1804, M. Myriel était curé de B. (Brignolles). 

# 2
Il était déjà vieux, et vivait dans une retraite profonde.

J'ai essayé ceci et quelques variantes sans grand succès :

1
2
[^.?!]*[.?!][^A-Z\.]
[^.?!]*[^A-Z\.?!]

Mais sans grand succès, ma plus grande difficulté étant encore de détecter le 'Mme'..

Je suis très à l'aise avec la théorie des langages mais je n'ai pas l'habitude de gérer ça sur un ordi :/

Merci d'avance :)

+0 -0
Auteur du sujet

Mon vrai but c'est de faire de l'IA avec (projet de recherche en option à la fac), sauf que pour utiliser les outils que j'ai trouvé il faut que je découpe un fichier avec une phrase par ligne. Le problème c'est que les phrases sont coupées par des sauts de lignes et les autres problèmes exposés.

Je connais la théories des langages mais je ne m'en suis jamais servi en pratique, construire, sur papier, une expression régulière aussi simple n'est pas trop problèmatique, en revanche la "coder" l'est.

Le texte ce sont les misérables que j'ai récupéré via le projet gutenberg en html :)

+0 -0
Staff

Cette réponse a aidé l'auteur du sujet

D'accord. Du coup tu ferais mieux d'utiliser des outils existants. Découper un texte en phrase est un problème complexe, et il y a des décennies de recherche qui s'y intéressent.

Le meilleur outil pour faire ça est très probablement de Stanford. Utilise le tokenizer avec tokenize,ssplit. ssplit signifie "sentence split". Evidemment tu vas devoir utiliser le FrenchTokenizer si ton texte est en français.

Je parle de JavaScript et d'autres trucs sur mon blog : https://draft.li/blog

+2 -0
Auteur du sujet

Bonjour, je déterre un peu ce sujet pour éviter d'un ouvrir un sur le même sujet. (D'ailleurs, j'ai plus ou moins abandonné ce dont on parlait avant parce que c'est vachement compliqué pour un truc simple, j'ai utilisé une regex basique et fini le travail à la main)

Maintenant, je dois travailler en lua, sauf que j'ai des petits problèmes ^^

J'ai un texte comme ceci :

1
F'; 5 5 5 5 5 5 4 4 4 2 2 5 1 1 1 0 4 4 3 3 3 2 2 5 1 1 1 0 4 4 3 3 3 2 2 5 1 1 1 0 4 4 3 3 3 2 2 2 0 0 0 0 0 0

Et j'aimerais avoir en sortie un dictionnaire :

1
{"F'":"5 5 5 5 5 5 4 4 4 2 2 5 1 1 1 0 4 4 3 3 3 2 2 5 1 1 1 0 4 4 3 3 3 2 2 5 1 1 1 0 4 4 3 3 3 2 2 2 0 0 0 0 0 0"}

Bon, jusque là j'y arrive. J'ai trouvé ma petite regex (l'idée c'est surtout de récupérer la première partie, la deuxième est simple) :

1
"[UDBFRL]['2]?;"

Maintenant je souhaite enrichir la chose et avoir un texte comme ceci :

1
R'F2BU2; 1 2 3 4 5 6...

Je pensais "bêtement" faire ceci comme regex, mais ça ne fonctionne pas :

1
"([UDBFRL]['2]?)+[;]"

Et je comprends pas pourquoi ça fonctionne pas, en regardant la doc c'est pourtant ce qui me semble possible. Est-ce le fait que ce soit en lua, sachant que je n'ai pas le choix sur le langage. Le vrai problème c'est que j'ai plusieurs lignes avec ce même genre de pattern et que je dois (évidemment) distinguer les lignes, si vous avez une solution alternatives, je suis preneur aussi :)

Merci d'avance :)

Édité par Ricocotam

+0 -0

Cette réponse a aidé l'auteur du sujet

Celle-là fonctionne comme tu l'attends ? ((?:[UDBFRL]['2]?)+);

Tu capturais un groupe, mais tu répétais 1 à infini fois le groupe, donc tu ne recevais que le dernier groupe matched. Ici, j'utilise un non-capturing group que je répètes $[1; +\infty[$ fois et je captures la répétition. Les [] sont inutiles si tu n'as qu'un caractère dedans.

Édité par tleb

It goes against the grain of modern education to teach children to program. What fun is there in making plans, acquiring discipline in organizing thoughts, devoting attention to detail and learning to be self-critical? – Perlis

+0 -0

Je ne comprends pas pourquoi tu as besoin de regexp, pourquoi est-ce que tu ne fais pas par exemple un split sur ";" ?

À mon avis, les regexp sont un outil puissant et agréable, à condition de les utiliser correctement, c'est-à-dire en évitant deux écueils :

  • Les utiliser pour des problèmes trop simples, c'est ce que tu fais ici. Il n'y a vraiment pas besoin d'une expression rationnelle pour récupérer tous les caractères qui précèdent un point-virgule, et ça ne rend certainement pas le programme plus simple à écrire ou plus lisible (la preuve, tu demandes de l'aide alors que tu y arriverais sans doute en 2 minutes avec une simple boucle).
  • Les utiliser pour des problèmes trop compliqués, c'est-à-dire essayer de reconnaître des langages qui ne sont pas réguliers en utilisant les constructions chimériques apportées dans les moteurs de regexp qu'on trouve souvent dans les langages mainstream. Typiquement, quand on commence à utiliser les groupes pour faire référence dans une regexp à ce qui a été matché précédemment par ladite regexp, c'est qu'il aurait mieux valu utiliser autre chose.

Un exemple intéressant de bonne utilisation des regexp est l'analyse lexicale d'un programme, où on part d'une chaîne de caractères (par exemple "while (x == 20) { x = x - 1 }") pour obtenir une liste de « mots » du langage (ici, quelque chose comme [While; LPar; Var("x"); IsEqual; Int(20); RPar; LCur; Var("x"); Assign; Var("x"); Minus; Int(1); RCur]).

Il y a aussi les exemples classiques comme reconnaître un numéro de téléphone ou une adresse mail correcte, mais je les aime moins, parce qu'ils sont foireux : il y a tellement de formats de numéro ou d'adresse un peu abscons que c'est déjà difficile d'écrire une regex valide, et à peu près impossible d'en écrire une compréhensible.

Édité par Eusèbe

+1 -0

Oula, tu n'es pas en train de recommander d'utiliser des regexps pour réaliser la partie analyse lexicale d'un interpréteur ou compileur, si ? C'est une très mauvaise idée :

  • c'est un problème trop compliqué.
  • la syntaxe n'est pas adapté pour ça. Il n'y a pas de symboles.
  • et surtout, il y a des syntaxes faites pour (BNF et consorts), qui sont bien plus lisibles et les implémentations sont bien plus performantes. Pour ceux qui veulent se plonger là dedans sans utiliser des langages trop bas niveaux et des concepts trop obscures, je vous conseille nearley (choix personnel, il existe d'autres libs accessibles comme ça pour votre language haut niveau de prédilection).

Les regexps valent le coup par contre pour de l'analyse statique de code (signaler un mauvais nombre d'espace entre une parenthèse fermante et une accolade ouvrante par exemple), c'est plus simple à mettre en place et on ne recherche que des cas spécifique dans le code, on ne cherche pas à analyser tous le code. On peut aussi ajouter des règles facilement.

Édité par tleb

It goes against the grain of modern education to teach children to program. What fun is there in making plans, acquiring discipline in organizing thoughts, devoting attention to detail and learning to be self-critical? – Perlis

+0 -1

Oula, tu n'es pas en train de recommander d'utiliser des regexps pour réaliser la partie analyse lexicale d'un interpréteur ou compileur, si ? C'est une très mauvaise idée :

tleb

Il a bien parlé de l'analyse lexicale et pas de la syntaxique. De plus le truc que tu proposes semble aussi utiliser des expressions rationnelles.

  • c'est un problème trop compliqué.

Non. Tu confonds analyse lexicale et analyse syntaxique, comme l'a dit entwanne. Ça fait certes un peu pointilleux de différentier les deux quand on parle de compilation, mais il s'agit malgré tout de deux problèmes différents, et les regexp sont adaptées pour le premier.

  • la syntaxe n'est pas adapté pour ça. Il n'y a pas de symboles.

Ça n'est pas le bon argument : c'est une question d'implémentation. Il n'y a rien qui dise que les expressions rationnelles doivent considérer l'alphabet ascii (ou n'importe quel ensemble de caractères que tu mets dans les string de ton langage préféré), et il existe tout un tas de moteurs de regexp qui permettent d'utiliser d'autres alphabets. Certes, pas re de python.

  • et surtout, il y a des syntaxes faites pour (BNF et consorts), qui sont bien plus lisibles et les implémentations sont bien plus performantes.

La même que plus haut : tu parles d'analyse syntaxique (obtenir un AST à partir d'une liste de lexèmes), pas d'analyse lexicale (obtenir une liste de lexèmes à partir d'une chaîne de caractères). Et ça fait effectivement partie des problèmes pour lesquels il faut quelque chose de plus puissant que les expressions rationnelles, cf. le deuxième point de mon message précédent.

Les regexps valent le coup par contre pour de l'analyse statique de code (signaler un mauvais nombre d'espace entre une parenthèse fermante et une accolade ouvrante par exemple), c'est plus simple à mettre en place et on ne recherche que des cas spécifique dans le code, on ne cherche pas à analyser tous le code. On peut aussi ajouter des règles facilement.

C'est un peu culotté de dire « l'analyse syntaxique c'est trop compliqué pour les regexp » et « l'analyse statique c'est une bonne utilisation des regexp » dans le même message :D

Le cas d'utilisation que tu décris est quelque chose d'excessivement simple (il n'y a même pas besoin de regex pour ça), et l'analyse statique est un domaine beaucoup plus vaste. Alors bien sûr, techniquement, on peut appeler n'importe quelle analyse de programme qui n'exécute pas ledit programme une analyse statique. Mais dans le cas général, c'est un problème qui est beaucoup beaucoup beaucoup plus complexe (et intéressant) que savoir si oui ou non on a bien mis le bon nombre d'espaces entre le if et l'accolade qui suit. Les « analyses statiques » qui fonctionnent avec des regexp en sont un micro sous-ensemble, et concrètement, on ne peut en gros rien faire d'intéressant avec. Par exemple, même une simple propagation de constantes est hors de portée.

Édité par Eusèbe

+1 -0
Staff

Les expressions rationnelles servent à produire des automates : quel que soit l'outil que tu utilises pour produire des tokens (donc faire une analyse lexicale), tu te retrouveras très certainement avec un automate en backend. Un simple coup d'oeil au Dragon Book suffit à le confirmer : plus de la moitié de la partie qui aborde l'analyse lexicale est occupée par la théorie sur les automates finis et les expressions rationnelles.

Edit: Désolé d'être tatillon mais :

et il existe tout un tas de moteurs de regexp qui permettent d'utiliser d'autres alphabets. Certes, pas re de python.

1
2
3
4
5
>>> r = re.compile('ጴ')
>>> r.findall('plopጴ')
['ጴ']
>>> r.findall('plop')
[]

re gère la totalité d'Unicode. Certes il a des limitations, certaines versions ne gèrent pas plus de 100 groupes nommés (ce qui peut être embêtant pour une analyse lexicale), le moteur repose sur un algo de backtracking dans le cas général pour autoriser des horreurs comme le lookahead, et il y a évidemment moyen de le défoncer (lui et n'importe quel cousin des PCRE en fait) en performances pour certaines catégories de problèmes, mais il gère proprement l'Unicode et les chaînes binaires.

Édité par nohar

I was a llama before it was cool

+1 -0

Les expressions rationnelles servent à produire des automates : quel que soit l'outil que tu utilises pour produire des tokens (donc faire une analyse lexicale), tu te retrouveras très certainement avec un automate en backend. Un simple coup d'oeil au Dragon Book suffit à le confirmer : plus de la moitié de la partie qui aborde l'analyse lexicale est occupée par la théorie sur les automates finis et les expressions rationnelles.

Je ne sais pas trop à qui tu réponds, mais histoire d'être sûr qu'il n'y ait pas d'ambiguité, c'est exactement ce que je dis :)

Pour re et l'unicode, je me cite :

Il n'y a rien qui dise que les expressions rationnelles doivent considérer l'alphabet ascii (ou n'importe quel ensemble de caractères que tu mets dans les string de ton langage préféré), et il existe tout un tas de moteurs de regexp qui permettent d'utiliser d'autres alphabets.

;)

Il est tout-à-fait possible que je me trompe (ça fait quelques années que je n'ai plus utilisé re), mais il me semble que tu ne peux pas définir ton propre alphabet (par exemple, un alphabet où les caractères seraient While ou Int). Certes, on a assez rarement besoin d'utiliser des regexp sur autre chose que des chaînes de caractères (encore que ça arrive), mais mon propos était simplement de dire que ce n'était pas le bon argument pour les disqualifier quand il s'agit d'analyse syntaxique (où on traite effectivement des mots sur ce genre d'alphabet).

Édité par Eusèbe

+0 -0
Staff

Je ne sais pas trop à qui tu réponds, mais histoire d'être sûr qu'il n'y ait pas d'ambiguité, c'est exactement ce que je dis :)

Pardon, je répondais à tleb juste au-dessus.

Il est tout-à-fait possible que je me trompe (ça fait quelques années que je n'ai plus utilisé re), mais il me semble que tu ne peux pas définir ton propre alphabet (par exemple, un alphabet où les caractères seraient While ou Int). Certes, on a assez rarement besoin d'utiliser des regexp sur autre chose que des chaînes de caractères (encore que ça arrive), mais mon propos était simplement de dire que ce n'était pas le bon argument pour les disqualifier quand il s'agit d'analyse syntaxique (où on traite effectivement des mots sur ce genre d'alphabet).

OK, je vois ce que tu veux dire : tu parles de regexp comme un langage formel de définition d'automates. Dans ce genre de cas on a effectivement plutôt tendance à générer un automate explicitement pour une grammaire quelconque (ce que fait yacc, par exemple). On est d'accord.

I was a llama before it was cool

+0 -0
Auteur du sujet

Quoi que vous pensiez, et puissiez argumenter, je n'ai pas le choix sur l'utilisation de regexp puisqu'en lua il n'existe pas de méthode split native, on est obligé de passer par des regexp :)

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte