Négation dans une expr régulière

Fermé
Igor - 13 mars 2006 à 11:04
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 - 14 mars 2006 à 18:46
Bonjour,
J'ai un problème vis-à-vis d'une expression régulière afin d'exprimer une négation sur une chaîne de caractères.
Je travaille avec des regexpr Javascript mais mon problème est je pense plus général...
J'ai un texte HTML dans lesquel je souhaite retirer toute les balises sauf les balises "annotation". Je vais donc utiliser un replace mais pour l'instant je teste avec un match afin de trouver mes motifs à remplacer.
J'utilise donc l'expr:
/</?[^>]*>/gi
celle-ci me trouve toutes les balises, normal
ensuite afin d'éliminer les balises annotion je me suis diriger vers
/</?[^annotation][^>]*>/gi
Ceci ne fonctionne bien évidemment pas car le circonflex au debut des crochets suivi de caractères veux dire "aucun de ces caractères". Pas bon dans mon cas, car je souhaite me baser sur une chaîne de caratères.
J'ai ensuite tenter un truc du genre
/(</?(?:[^a]|a[^n]|an[^n]|ann[^o])[^>]*>?)/gi
La regExpr ci dessus voudrait dire toutes les balises sauf les balises "anno". J'ai déja fais des choses comme ça en python mais dans mon cas cela n'a pas l'air de fonctionner.
J'imagine que vu que je veux repérer la chaîne annotation il faut la mettre entre pararenthèses et ensuite exprimer une négation sur celle-ci mais je n'arrive pas à mon but !!!!!
Quelqu'un aurai-t-il une idée s'il vous plaît ???? merci

10 réponses

kiruasam Messages postés 36 Date d'inscription lundi 27 février 2006 Statut Membre Dernière intervention 11 mai 2006 3
13 mars 2006 à 12:12
Tu as deja essayé ça je suppose :
/</?^annotation[^>]*>/gi

C'est la meme chose que tu as essayé au début mais sans les crochets, en effet :
"^annotation" -> chaine qui commence par annotation
(voir http://www.commentcamarche.net/php/phpreg.php3)

J'ai pas de quoi tester là, donc je peux pas t'aider plus mais normalement c'est pas beaucoup compliqué que ça.

Bon courage
0
Merci, j'avais tester déjà cela mais ca ne fonctionne malheureusement pas car le circonflex ne peut être utilisé de cette manière...
tant pis, je vais faire mon algo différement ...
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
13 mars 2006 à 16:59
Salut,

/</?[^annotation][^>]*>/

Je n'ai pas vraiment le temps pour l'instant mais je vais discuter ça.

C'est normal que ça ne marche pas puisque tu as une classe de caractère [annotation] qui veut dire trouve moi un élément qui n'est pas dans [^.....]

Mais il parle de non a non n non n non o non t non a non t non i non o non n mais pas de a suis de n suis de n suis de o suis de t suis de a suis de t suis de i suis de o suis de n

C'est la meme chose que tu as essayé au début mais sans les crochets, en effet

Et ça c'est vraiment faux.

Je pense que c'est mieux de faire une boucle qui passe tout les chaines de caracteres mais qu'il saute les balises dont elles contient annotation
0
Merci pour vos réponses,
Je n'ai tjs pas réussi à faire ce que je voulais au début mais j'ai pu modifier mon algo afin d'arriver à mes fins sans passer par l'élimination des balises sauf la balises "annotation".
Merci quand même à tout le monde
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
TuXor Messages postés 97 Date d'inscription lundi 23 mai 2005 Statut Membre Dernière intervention 28 avril 2006 25
14 mars 2006 à 14:42
Hello,

Je suis peut étre totalement a coté de la plaque,

mais est-ce que vous avez essayé un truc du genre ^(annotation ) ?

histoire de grouper les lettres, pour qu'elles soient considérées comme un mot et non pas une suite de charactères.
0
Merci,
je ne pense pas avoir tester cela
je pense de toute manière que l'expression régulière
^(annotation)
est mal formée car le ^ ne peut être utilisé que dans deux cas à savoir:
1/ [^abcd]
--> cela veut dire: 1 caractère qui ne soit pas ni a ni b ni c ni d (les crochets représentant 1 caractère)
pour annotation on aurait pu faire:
[^anoti]{10} --> 10 caractères qui ne soit ni .... du coup pas "annotation" mais pas "onnatitaon" non plus (or dans mon cas je cherche vraiment "annotation")
2/ ^annotation
--> tous les mots commençant pas annotation, donc "annotationaa" correspond aussi à ce motif, cela ne correspond pas à la négation de la chaîne "annotation".

Pour avoir souvent été confronté à ce problème avec la manipulation d'expression régulière (Ne me trouve pas cette chaîne de caractères) je ne suis pas sur qu'il soit possible de réaliser une telle regExpr de manière simple (le troisième exemple de mon premier post est une regExpr qui devrait marcher mais elle est totalement inefficace, lente et très gourmande pour avoir déjà eu des Memory error avec ce type de regExpr).
Dans tous les cas j'ai du revoir mon algo afin de ne plus avoir à réaliser une recherche de ce type. C'est pas bien grave et on trouve tjs une solution
je sais pas qui disait que l'ensemble des solutions est tjs supèrieur à l'ensemble des questions...
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
14 mars 2006 à 15:59
Salut,

J'ai étudié un peu ton problème.

si on a une balise par ligne ce n'est pas difficile, une boucle qui saute la ligne fait l'affaire.

Mais je ne crois pas que c'est le cas.

En ce cas une solution c'est de passer chaque ligne et sur chaque ligne de faire une detection progressive des balises qu'on cherche ou qu'on veut eviter.

Il faut aussi prendre en compte la posibilité d'avoir une balise qui s'etends sur plusieurs lignes.

J'aimerai bien avoir ton fichier pour tester. Tu peux utiliser http://cjoint.com/
0
Et on continue.....
Alors mon problème été le suivant:
sur une page HTML après une séléction d'une partie du texte je surligne avec une couleur de fond le texte séléctionné
--> je fais ça en Javascript en utilisant le DOM du doc HTML afin d'entourer le texte précédement sélectionné avec une balise "annotation" sur laquelle je défini un background-color pour le surlignage. Cette balise possède un attribut id.

Mon but était de localiser le texte sélectionné afin de repérer mon annotation par rapport à mon texte, qu'il soit en format HTML ou en format Doc, ou rtf, ou je sais pas... donc en me basant sur le texte pur.
Du coup je voulais suprimer toutes les balises de la page brut pour ensuite repérer quel était la nième occurence du texte qui avait était mis en valeur.
donc 1 --> suprimer les balises sauf la balise annotation
2 --> calculer l'occurence

J'ai changer en récupérant premièrement tout le texte "à gauche" de ma balise annotation, en éliminant la-dessus toutes les balises et ensuite en calculant le nombre d'occurence
Afin d'obtenir un truc du genre:
texte: le
occurence: 20

--> 20ème occurence du texte "le"

Ensuite je fais tout mon truc, stockage dans ma base XML et ainsi de suite

voici ma méthode qui calcule mon nb d'occurence si tu veux :

function calculateOccurence() {
var text = document.getElementById("doc_html").innerHTML;
// on cherche la balise annotation qui correspond
motif = new RegExp("<annotation[^>]*id=\""+idAnnot+"\"[^>]*>", "i");
searchAnnot = text.match(motif);
// on recupere le texte precedent
txtBefore = RegExp.leftContext;
// on élimine toutes les balises
balises = new RegExp("</?[^>]*[^>]*>", "gi");
txtEpure = txtBefore.replace(balises,'');
// on calcule le nb d'occurence du motif annoté puis on le retourne
var flag = 1;
var occur = 1;
// bodyAnnot correspond au texte annoté
annotRE = new RegExp(bodyAnnot, "i");
while (flag != 0) {
searchOccur = txtEpure.match(annotRE);
if (searchOccur==null) {
flag = 0;
}
else {
occur = occur + 1;
txtEpure = RegExp.rightContext;
}
}
return occur;
}
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
14 mars 2006 à 16:47
Et on continue....

Je ne connais pas java, je travaille en perl, mais ici il s'agit de regex dont l'implémentation ce n'est pas la même.

Pour trouver une occurence dans perl je fais quelque chose de genre
while ( $var =~ /b/g) {
      print "b trouvé dans la postion pos($var) - 1.\n";
}

Donc dans un context scalarie le modificateur g permet une recherche progressive.

Dans un contexte de liste on obtient les occurences.
En ce cas le nbr des occurence on les obtiens en utilisant la liste dans un context scalaire ( @nb + 0 ou scalar @nb )
@nb = svar =~ /b/g


Je vais essayer de faire un script en perl pour traiter ton problème (disons un cas général) vu que maintenant je sais ce que tu veux.

J'aimerai quand même avoir une partie ou le fichier entière ainsi que un exemple concret de résultat que tu veux obtenir.

Je préfère connaître la structure de fichier avant de me lancer avec les regex (puisque en fait le but de regex est de faire correspondre et pas de ne pas correspondre).

Peut être tu vas demander pourquoi?
Ben il y a plein des questions que je me pose.

tu as une balise par ligne ou plusieurs?
entre les balises tu as des espaces, tabulations ou elles sont collées

debut/><fin ou debut/> <fin

les balises tiens sur une seule ligne?

<balise ....../>

ou sur plusieurs

<balise....
.....
/>

?
0
Re,
c'est très gentil de t'intéresser de si près à mon problème (qui je répête n'en est plus un car j'ai réussi à faire ce que je voulais depuis, mais bon).
Le texte dans lequel je dois calculer mon occurence ne m'est pas connu, il s'agit de n'importe quel texte HTML (bien formé ou non d'ailleur), alors maintenant, sur une ligne, plusieurs, avec des balises sur une ou plusieurs lignes aussi, des balises qui s'ouvre et qui ne se ferme pas .... enfin tous ce que l'on trouve sur le net!!

Ensuite il faut que cela marche en JavaScript, c'était ma principal difficulté car je travaille habituellement en python. J'aurai pu faire un fameux coup d'Ajax pour transmettre le fichier complet à mon serveur et faire les traitements cotés serveur mais comme je voulais un mode dégradé cela aurait fait beaucoup d'appel et une charge trop lourde, donc du coup faut le faire coté client.....
voial l'explication
pour finir le résultat voulu est:
texte: salut
occurence: 16
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
14 mars 2006 à 18:46
Le plus important c'est que tu as reussi obtenir le résultat que tu voulais.

Bonne continuation.
-1