Java Pattern Regex : tout sauf une chaine

[Fermé]
Signaler
-
 Hawat -
Bonjour,

je touche depuis quelques temps aux expressions java et je ne trouve pas comment tout matcher sauf une sous chaine spécifier.

Exemple : je veux tout matcher sauf foo

foo -> pas matché
bar foo -> pas matché
bar -> matché

j'essaie avec (?!(foo)) mais cela ne fonctionne pas...

j'utilise http://www.regexplanet.com/simple/index.html pour tester mes regex rapidement.

Merci pour votre aide

2 réponses

Bonjour,

Bijnok tu veux t'attaquer aux expressions régulières et c'est une bonne chose mais tu dois d'abord comprendre ce que veux dire "matcher". Une expression régulière est la description de ce que peut être une chaine. On se sert des expressions régulières (regexs) à la base pour trouver ou extraire une chaine de caractère qui matche donc une regex; c'est à dire une chaine qui correspond précisément à la définition énoncée par la regex.
Comme le dis KX, si tu cherche à savoir si une chaine contient foo ou non, les regexs ne sont pas adaptées et représentent même une contre performance; il vaut mieux utiliser la méthode contains des objets String qui renvoie exactement la même chose que indexOf("ce que tu cherche") != -1.
Maintenant si tu veux chercher (extraire) dans une chaine de caractère tout ce qui n'est pas "foo" tu peux utiliser les regexs(même s'il y a d'autres solutions plus performantes mais moins élégantes)
Ton pattern "(?!(foo))" veut dire: trouve une expression de longueur nulle qui n'est pas suivie de foo et, si la correspondance est trouvée, met la partie qui matche foo dans le groupe 1. Pas étonnant que tes tests ne fonctionnent pas
Explication :
1 - quand on match une regex on obtient un objet qui contient n groupes, si la correspondance est réussie le groupe 0 contient l'intégralité de la correspondance, le groupe 1 contient la première capture, le deuxième la deuxième capture etc... les captures sont définies par des paranthèses et numérotées dans l'ordre de la parenthèse ouvrante -> (1(2)(3))(4)
2 - les groupes définis par des parenthèses avec un ? sont non capturants: (?:), (?!), (?<) etc.... ils ne comptent donc pas dans la numérotation des groupes.

Finalement si tu veux quand même la solution:
matcher uniquement une chaine qui ne contient pas "foo" :
"^(?:f(?!oo)|[^f])*$"
La description exacte serait matche une chaine qui contient du début (^), à la fin ($), soit f à condition qu'il ne soit pas suivi de oo( f(?!oo)), soit(|) autre chose que f ([^f]) , le tout 0 à n fois (*).
Donc 0 à l'infini (enfin presque) caractères qui ne sont pas des f sauf s'ils ne sont pas suivis de "oo".
-> voilà pourquoi KX t'as orienté vers une autre solution: c'est couteux pour le programmeur et la machine alors qu'il suffirait de faire:

String ceQueJeVeux = ceQueJeTeste.contains("foo") ? null : ceQueJeTeste;

Les bases:
http://www.loribel.com/info/memento/regex.html

Quand tu as bien compris:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html

Désolé pour cette réponse si longue qui intervient si tard mais ceux qui prendront le temps de comprendre découvriront peut être la puissance de cet outil. Les programmeurs auraient une bien faible espérance de vie sans les expressions régulières......
11
Merci

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

CCM 65492 internautes nous ont dit merci ce mois-ci

Messages postés
16372
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
23 juillet 2021
2 861
Il y a plus simple que des expressions régulières pour faire ça :

static boolean match(String s)
{
	return s.indexOf("foo")==-1;
}
	
static void test(String s)
{
	System.out.println(s+" --> "+match(s));
}

public static void main(String...args)
{
	test("foo");
	test("bar foo"); 
	test("bar");
}