Précédent   Forum du club des développeurs et IT Pro > Autres langages > Perl > Langage
Langage Toutes vos questions sur les scripts Perl en général. Avant de poster, veuillez consulter les FAQs perl, les cours Perl, les critiques de livres et les sources Perl.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 04/01/2013, 16h36   #1
edensoul
Invité de passage
 
Homme
Étudiant
Inscription : janvier 2013
Messages : 3
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : janvier 2013
Messages : 3
Points : 1
Points : 1
Par défaut Conseils pour correcteur orthographique

Bonjour je dois créer un correcteur orthographique en perl qui doit effectuer quatre tâches différentes: l'insertion de caractères, la substitution, la suppression et la transposition. Puis mettre les corrections dans un nouveau fichier.

Il doit aussi prendre en compte l'accentuation des mots, ce que je n'ai pas encore réussi à trouver pour le moment.

De même pour l'insertion de caractère, il semble qu'un splice ne soit pas suffisant pour cette opération, car pour le mot mal orthographié "lou" il ne trouve pas le mot "loup" dans le dictionnaire.



Voici donc mon code:


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
 
#!/usr/bin/perl -w
 
use strict;
use utf8;
binmode(STDOUT, ":encoding(utf8)");
binmode(STDIN, ":encoding(utf8)");
 
my $alphafr;
my ($mot_errone, $ligne, $ligne1, $ligne2, $elt, $m, $transposition, $lettre1, $lettre2, $suppression,$insertion,$substitution, $choix,
@mot, @mot_modifie, @fichier_dicfr, @texte, @dicfr, @insertion, @substitution, @transposition, @suppression, @propositions);
 
my %ponctuation = (
	' '   => 1,
	''    => 1,
	','   => 1,
	"'"   => 1,
	'.'   => 1,
	'‒'   => 1,
	';'   => 1,
	'!'   => 1,
	'-'   => 1,
	':'   => 1,
	'?'   => 1
);
 
 
 
#les mots du lexique sont stockés dans une tableau
my $fichier_dicfr= "lexique.txt";
open (LEXFR, "<:encoding(utf8)", $fichier_dicfr);
while (defined ( $ligne = <LEXFR>)){
	chomp $ligne;
	@fichier_dicfr = split (/\s/, $ligne);
	push (@dicfr, @fichier_dicfr);
}
close (LEXFR);
 
 
print "Bonjour, quel est le nom du fichier à analyser ?\n";
 
#entrée du fichier à corriger par l'utilisateur
my $fichier = <STDIN>;
chomp $fichier;
open (FCHFR,"<:encoding(utf8)", $fichier);
 
#création de la version corrigée
my $fichier_corrige = "correction.txt";
open (COR, ">:encoding(utf8)", $fichier_corrige);
 
 
print "Voici les fautes repérées et mes suggestions de correction \n";
 
while (defined ($ligne1 = <FCHFR>)) {
	chomp $ligne1;
	@texte = split (/(\pP|\pS|\s)/, lc $ligne1);
	#Capture des mots non présents dans le lexique
	for (my $i=0; $i < @texte; $i++) {
		if (!grep (/^$texte[$i]$/, @dicfr) and not exists ($ponctuation{$texte[$i]})){
			push (@mot, $texte[$i]);
			$mot_errone = $texte[$i];
			print "Ligne $. : L'orthographe du mot  $mot_errone est erronée\n";
			print "Quelle correction souhaitez-vous appliquer ? (indiquez le chiffre, ou 0 si aucune correction ne vous convient)\n";{
				#liste des mots non trouvés dans le lexique
				foreach $m(@mot){
					@mot_modifie = split (//, $m);
					open (LEXFR, "<:encoding(utf8)", $fichier_dicfr);
						while (defined ($ligne2 = <LEXFR>)){
							chomp $ligne2;
							@fichier_dicfr = split (/\s/, $ligne2);
							push (@dicfr, @fichier_dicfr);
						}
						#Boucle pour la transposition lcou devient clou
						for (my $i = 0; $i < $#mot_modifie; $i++){
							@transposition = @mot_modifie;
							$lettre1 = $transposition[$i];
							$lettre2 = $transposition[$i+1];
							$transposition [$i] = $lettre2;
							$transposition [$i+1]= $lettre1;
							$transposition = join "", @transposition;
								if (grep (/^$transposition$/, @dicfr)){
									push (@propositions, $transposition);
								}
						}
 
						#Boucle pour la suppression hommme devient homme
 
					foreach $elt (0..$#mot_modifie) {
						@suppression = @mot_modifie;
						splice (@suppression, $elt, 1);
						$suppression = join "", @suppression;
						if (grep (/^$suppression$/, @dicfr)){
							push (@propositions, $suppression);
						}
 
						#Boucle pour l'insertion homm devient homme
 
						foreach $alphafr ('a'..'z'){
							@insertion= @mot_modifie;
							splice (@insertion, $elt, 0, $alphafr);
							$insertion = join "", @insertion;
							if (grep (/^$insertion$/, @dicfr)){
								push (@propositions, $insertion);
							}
						#Boucle pour la substitution lou devient cou
 
							@substitution = @mot_modifie;
							splice(@substitution, $elt, 1, $alphafr);
							$substitution = join "", @substitution;
							if (grep (/^$substitution$/, @dicfr)){
									push (@propositions, $substitution);
							}
						}
					}
 
				}
			}
			#Affichage des propositions et choix de l'utilisateur
			print "@propositions\n";
			$choix =<STDIN>;
			chomp $choix;
			#Remplacement du mot mal orthographié dans la ligne correspondante 
			$ligne1 =~s/$mot_errone/$propositions[$choix]/;
		}	
	}
	#création du fichier corrigé
	print (COR $ligne1);
}
close (LEXFR);
close (FCHFR);
close (COR);
Fichiers attachés
Type de fichier : zip lexique.zip (58,0 Ko, 6 affichages)
edensoul est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2013, 13h03   #2
Lolo78
Membre Expert
 
Homme Laurent R.
Conseil - Consultant en systèmes d'information
Inscription : mai 2012
Messages : 568
Détails du profil
Informations personnelles :
Nom : Homme Laurent R.
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : mai 2012
Messages : 568
Points : 1 118
Points : 1 118
Hum, ce n'est pas un problème simple.

Déjà, il faut tenir compte des différentes formes que prennent les mots (pluriel, féminin, conjugaisons, etc.). Il faut également tenir compte des accents, des nombres, des tirets et des apostrophes, etc. Cela peut être fait dans le lexique, mais ça alourdit considérablement ce lexique.

Tu règles le problème des majuscules en mettant tout en minuscule, mais cela veut dire que tu ne verras pas une erreur comme les mots "angleterre" ou "allemagne" écrits sans la majuscule.

Ensuite, trouver tous les mots qui ne figurent pas dans le lexique n'a rien de bien complexe (bien qu'il puisse y avoir des considérations de performance à prendre en ligne de compte), mais trouver les mots qui "ressemblent" pour proposer une correction possible est bien plus difficile. Il faut alors, d'une façon ou d'une autre, essayer de définir une forme de "distance" entre deux mots en fonction du nombre de lettres différentes et de leur ordre, afin de pouvoir proposer les mots du dictionnaire les moins distants des mots non trouvés dans le texte à analyser.

En termes de performances, stocker les mots du dictionnaire dans une table de hachage est certainement une bien meilleure solution que dans un tableau, la recherche sera considérablement plus rapide.

Il y a une discussion intéressante de ce problème dans le livre "Programming Pearls" (j'ai bien écrit "Pearls", ça n'a rien à voir avec le langage Perl), de Jon Bentley (chapitre 13). Ce bouquin peut être téléchargé gratuitement au format PDF (avec un filigrane assez gênant en bas de chaque page, mais, bon, pour suivre globalement la discussion, ça reste utilisable).
__________________
Sauf mention contraire explicite, les bouts de code que je poste en réponse à une question n'ont pas forcément été testés.
Lolo78 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2013, 19h51   #3
edensoul
Invité de passage
 
Homme
Étudiant
Inscription : janvier 2013
Messages : 3
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : janvier 2013
Messages : 3
Points : 1
Points : 1
Tout d'abord merci pour vos conseils.

Effectivement la lecture du tableau est assez fastidieux.

Je vais voir ce que je peux faire pour mettre le lexique dans une table.

Et merci pour la recommandation du livre


EDIT:

après chargement du lexique dans une table de hashage l'affichage est vraiment plus rapide

Les seuls problèmes qu'il me reste à résoudre sont : l'accentuation, l'ajout de lettre à la fin du mot (bizarrement cela fonctionne pour le début mais pour la fin. J'obtient par exemple pour "lou" = "clou" ou "flou" mais pas "loup" ni "loué"


Et j'aimerais savoir comment faire pour quand l'utilisateur entre "0" le mot considéré comme erroné reste tel quel dans la correction ( sûrement une histoire de condition ...)

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/perl
 
use warnings;
use strict;
use utf8;
binmode(STDOUT, ":encoding(utf8)");
binmode(STDIN, ":encoding(utf8)");
 
my $alphafr;
my ($mot_errone, $ligne, $ligne1, $ligne2, $elt, $m, $transposition, $lettre1, $lettre2, $suppression,$insertion,$substitution, $choix,
@mot, @mot_modifie,@texte, @insertion, @substitution, @transposition, @suppression, @propositions);
 
my $n=0;
 
my %lexique;
 
#table de hash pour ne pas prendre ne compte la ponctuation et les espaces vides
my %ponctuation = (
	' '   => 1,
	''    => 1,
	','   => 1,
	"'"   => 1,
	'.'   => 1,
	'&#8210;'   => 1,
	';'   => 1,
	'!'   => 1,
	'-'   => 1,
	':'   => 1,
	'?'   => 1
);
 
#les mots du lexique sont stockés dans une tableau
my $fichier_dicfr= "lexique.txt";
open (LEXFR, "<:encoding(utf8)", $fichier_dicfr);
while (defined ( $ligne = <LEXFR>)){
	chomp $ligne;
	$lexique{$ligne} = 1;
}
close (LEXFR);
 
 
print "Bonjour, quel est le nom du fichier à analyser ?\n";
 
#entrée du fichier à corriger par l'utilisateur
my $fichier = <STDIN>;
chomp $fichier;
open (FCHFR,"<:encoding(utf8)", $fichier);
 
#création de la version corrigée
my $fichier_corrige = "correction.txt";
open (COR, ">:encoding(utf8)", $fichier_corrige);
 
 
print "Voici les fautes repérées et mes suggestions de correction \n";
 
while (defined ($ligne1 = <FCHFR>)) {
	chomp $ligne1;
	@texte = split (/(\pP|\pS|\s)/, $ligne1);
	#Capture des mots non présents dans le lexique
	for (my $i=0; $i < @texte; $i++) {
		if (not exists ($lexique{$texte[$i]})and not exists($ponctuation{$texte[$i]})){
			push (@mot, $texte[$i]);
			$mot_errone = $texte[$i];
			print "Ligne $. : L'orthographe du mot  $mot_errone est erronée\n";
			print "Quelle correction souhaitez-vous appliquer ? (indiquez le chiffre, ou 0 si aucune correction ne vous convient)\n";{
				#liste des mots non trouvés dans le lexique
				foreach $m(@mot){
					@mot_modifie = split (//, $m);
					open (LEXFR, "<:encoding(utf8)", $fichier_dicfr);
						while (defined ($ligne2 = <LEXFR>)){
							chomp $ligne2;
							$lexique{$ligne2} = 1;
						}
						@propositions=();
						#Boucle pour la transposition lcou devient clou
						for (my $i = 0; $i < $#mot_modifie; $i++){
							@transposition = @mot_modifie;
							$lettre1 = $transposition[$i];
							$lettre2 = $transposition[$i+1];
							$transposition [$i] = $lettre2;
							$transposition [$i+1]= $lettre1;
							$transposition = join "", @transposition;
								if (exists ($lexique{$transposition})){
									push (@propositions, $transposition);
								}
						}
 
						#Boucle pour la suppression hommme devient homme
 
					foreach $elt (0..$#mot_modifie) {
						@suppression = @mot_modifie;
						splice (@suppression, $elt, 1);
						$suppression = join "", @suppression;
						if (exists ($lexique{$suppression})){
							push (@propositions, $suppression);
						}
 
						#Boucle pour l'insertion homm devient homme
 
						foreach $alphafr ('a'..'z'){
							@insertion= @mot_modifie;
							splice (@insertion, $elt, 0, $alphafr);
							$insertion = join "", @insertion;
							if (exists ($lexique{$insertion})){
								push (@propositions, $insertion);
							}
						#Boucle pour la substitution lou devient cou
 
							@substitution = @mot_modifie;
							splice(@substitution, $elt, 1, $alphafr);
							$substitution = join "", @substitution;
							if (exists ($lexique{$substitution})){
									push (@propositions, $substitution);
							}
						}
					}
 
				}
			}
			#Affichage des propositions et choix de l'utilisateur
			#$n++;
			print "@propositions\n";
			#$n=0;
			$choix =<STDIN>;
			chomp $choix;
			#Remplacement du mot mal orthographié dans la ligne correspondante 
			$ligne1 =~s/$mot_errone/$propositions[$choix]/;
		}	
	}
	#création du fichier corrigé
	print (COR $ligne1);
}
close (LEXFR);
close (FCHFR);
close (COR);
edensoul est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2013, 00h00   #4
Lolo78
Membre Expert
 
Homme Laurent R.
Conseil - Consultant en systèmes d'information
Inscription : mai 2012
Messages : 568
Détails du profil
Informations personnelles :
Nom : Homme Laurent R.
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : mai 2012
Messages : 568
Points : 1 118
Points : 1 118
Citation:
Envoyé par edensoul Voir le message

Et j'aimerais savoir comment faire pour quand l'utilisateur entre "0" le mot considéré comme erroné reste tel quel dans la correction ( sûrement une histoire de condition ...)
La substitution ne se fera pas quand l'utilisateur tape 0 si tu écris ta ligne de code comme ceci:

Code :
$ligne1 =~s/$mot_errone/$propositions[$choix]/ if $choix;
Ainsi, la substitution ne se fait pas si $choix = 0 ou si choix n'est pas défini (vide).

L'autre solution est de commencer par mettre le mot supposé erroné dans le tableau @propositions (comme premier élément du tableau), en sorte que $propositions[0] soit ce mot. Dans ce cas, si l'utilisateur tape 0, le mot erroné est remplacé par lui-même.

Pour l'accentuation, je passe mon tour pour l'instant car je ne vois pas très bien quel est le problème. En général, je ne travaille que sur de l'ASCII 7 bits et je ne connais donc pas très bien les problématiques Unicode/UTF8/etc., mais je n'ai pas rencontré de difficulté particulière les quelques fois où j'ai eu besoin de comparer des textes et fichiers ayant des mots accentués: je suppose que les mots étant encodés de la même manière des deux côtés, le programme se débrouillait pour s'y retrouver. Ou alors, peut-être que ma machine ou mon installation de Perl était paramétrée correctement, avec le bon "locale" pour gérer les caractères accentués français, cédilles, etc. Il s'agissait d'un gros serveur sur lequel je n'ai aucun contrôle, l'installation de Perl a été faite à ma demande par un administrateur système, mais j'ignore ce qu'il a fait précisément.

J'ai notamment eu besoin de valider des adresses mail (ou, plutôt, le contraire, de détecter des adresses invalides). La présence d'un caractère accentué était une cause d'exclusion. Je n'ai eu aucun problème à détecter des adresses de la forme "toto.titi@numéricable.fr" et à les remplacer par une version avec le même caractère non accentué avec une commande du genre : "tr/àéèùôç/aeeuoc/", pour obtenir: "toto.titi@numericable.fr"

Par ailleurs, je viens de faire un petit essai sur mon PC perso avec Perl sous Cygwin, il a l'air de gérer tout aussi correctement les accents dans les cas simples. Par exemple, le code suivant:

Code :
1
2
my $c = "caméra";
print $c if $c =~ /(a|b)mér/;
m'imprime bien "caméra". Donc, ma version de Perl semble s'arranger des accents aussi bien dans la chaîne de caractère contenue dans la variable $c que dans l'expression régulière /(a|b)mér/. Je parviens même à utiliser un caractère utiliser dans la clef d'un hash:

Code :
1
2
$d{'caméra'} = "toto";
print $d{'caméra'}
fonctionne correctement, de même que:

Code :
1
2
3
my $c = "caméra";
$d{$c} = "toto";
print $d{$c};
Bref, je sais bien qu'il peut y avoir des problèmes avec les accents, en Perl comme dans d'autres langages, mais le pire n'est pas certain, il se peut que ça marche tout seul ou presque. Et si tu as eu des problèmes, explique leur nature.
__________________
Sauf mention contraire explicite, les bouts de code que je poste en réponse à une question n'ont pas forcément été testés.
Lolo78 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2013, 10h54   #5
edensoul
Invité de passage
 
Homme
Étudiant
Inscription : janvier 2013
Messages : 3
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : janvier 2013
Messages : 3
Points : 1
Points : 1
Je vais opter pour la solution de mettre le mot erroné en première position dans le tableau, ce qui est plus cohérent avec l'énoncé.

En ce qui concerne les accents c'est au niveau de l'insertion de lettres et de substitution que cela pose problème.

$alphafr ( 'a'..'z' ) ne prend pas les accents. Je pense créer un tableau contenant les lettres de l'alphabet français, logiquement cela devrait résoudre le problème.

EDIT1: j'ai résolu le problème d'insertion de caractère, il fallait rajouter +1 après $elt dans le splice

Code :
splice (@insertion, $elt+1, 0, $alphafr);
Maintenant j'ai bien "loup" de proposer pour le mot "lou", il ne manque plus que les accents... affaire à suivre...

EDIT2: mettre l'alphabet avec les accents dans un tableau à résolu le problème. Il me reste juste à changer le nom du fichier sortie pour plus de clarté "nomdufichier" - "corrigé" .txt

Encore merci pour votre aide
edensoul est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 13h42.


 
 
 
 
Partenaires

Hébergement Web