2010-11-27 7 views
4

Pour une raison quelconque ce morceau de code Java me donne les matchs qui se chevauchent:Éviter le chevauchement correspondant regex en Java

Pattern pat = Pattern.compile("(" + leftContext + ")" + ".*" + "(" + rightContext + ")", Pattern.DOTALL); 

aucune façon option/il évite la détection des chevauchements? par exemple. leftContext rightContext rightContext devrait être de 1 correspondance au lieu de 2

Voici le code complet:

public static String replaceWithContext(String input, String leftContext, String rightContext, String newString){ 
    Pattern pat = Pattern.compile("(" + leftContext + ")" + ".*" + "(" + rightContext + ")", Pattern.DOTALL); 
    Matcher matcher = pat.matcher(input); 
    StringBuffer buffer = new StringBuffer(); 

    while (matcher.find()) { 
    matcher.appendReplacement(buffer, ""); 
    buffer.append(matcher.group(1) + newString + matcher.group(2)); 
    } 
    matcher.appendTail(buffer); 

    return buffer.toString(); 
} 

Alors, voici la réponse finale à l'aide d'un test avant négatif, mon mauvais pour ne pas se rendant compte * était avide:

Pattern pat = Pattern.compile("(" + 
    leftContext + ")" + "(?:(?!" + 
    rightContext + ").)*" + "(" + 
    rightContext + ")", Pattern.DOTALL); 
+1

Pouvez-vous nous dire ce que leftContext et rightContext sont? Et donnez-nous un exemple de correspondance défaillante. – marcog

+1

Obtenir le matcher regex pour capturer des choses qui se chevauchent est généralement une question un peu délicate, pas quelque chose qui se passe par défaut. Sans voir le contenu des modèles, il est difficile de dire ce qui se passe. Cela nécessiterait essentiellement des balises pour que le matcher passe par-dessus la même partie de la corde plus d'une fois. Est-ce que vous faites ça? – tchrist

+0

rightContext et leftContext sont des chaînes simples e.g leftContext = "ab" rightContext = "cd" – Ricardo

Répondre

2

Votre utilisation du mot «chevauchement» prête à confusion. Apparemment, ce que vous vouliez dire, c'est que la regex est trop gourmande, correspondant à tout de la première leftContext à la dernière rightContext. Il semble que vous l'ayez déjà compris - et que vous ayez aussi trouvé une meilleure approche - mais il y a encore au moins un problème potentiel.

Vous avez dit leftContext et rightContext sont des "chaînes simples", par lesquelles je suppose que vous vouliez dire qu'ils ne sont pas censés être interprétés comme des expressions régulières, mais ils le seront. Vous devez leur échapper, ou tout méta-caractère regex qu'ils contiennent entraînera des résultats incorrects ou des exceptions d'exécution. La même chose vaut pour votre chaîne de remplacement, bien que seulement $ et le backslash ont des significations spéciales là-bas. Voici un exemple (notez le .*?, trop non gourmand):

public static String replaceWithContext(String input, String leftContext, String rightContext, String newString){ 
    String lcRegex = Pattern.quote(leftContext); 
    String rcRegex = Pattern.quote(rightContext); 
    String replace = Matcher.quoteReplacment(newString); 
    Pattern pat = Pattern.compile("(" + lcRegex + ").*?(" + rcRegex + ")", Pattern.DOTALL); 

Une autre chose: si vous ne faites aucun traitement post-match sur le texte correspondant, vous pouvez utiliser replaceAll au lieu de rouler votre propre avec appendReplacement et appendTail:

return input.replaceAll("(?s)(" + lcRegex + ")" + 
         "(?:(?!" + rcRegex + ").)*" + 
         "(" + rcRegex + ")", 
    "$1" + replace + "$2"); 
1

Il y a peu de possibilités, selon ce dont vous avez réellement besoin.

Vous pouvez ajouter $ à la fin de votre regex, comme ceci:

"(" + leftContext + ")" + ".*" + "(" + rightContext + ")$" 

donc si rightContext n'est pas la dernière chose, votre regex ne correspondra pas à.

Ensuite, vous pouvez capturer tout ce qui suit rightContext:

"(" + leftContext + ")" + ".*" + "(" + rightContext + ")(.*)" 

et après que jeter tout dans votre troisième groupe correspondant. Mais, puisque nous ne savons pas ce que sont vraiment et rightContext, peut-être que votre problème réside en eux.

+0

mm, je ne sais pas comment cela va fonctionner dans mon code, je ne peux pas simplement jeter des parties de la chaîne d'entrée – Ricardo