1
votes

Java RegEx ne remplace pas tout

J'essayais de remplacer le symbole de concaténation «+» par «||» dans un script multiligne donné, cependant il semble que java regex ne remplace qu'une seule occurrence, au lieu de toutes.

String ss="A+B+C+D";
Matcher mm=Pattern.compile("(?imc)(.+)\\s*\\+\\s*(.+)").matcher(ss);

while(mm.find())
{
    System.out.println(mm.group(1));
    System.out.println(mm.group(2));
    ss=mm.replaceAll("$1 \\|\\| $2");
}

System.out.println(ss); // Output: A+B+C||D, Expected: A||B||C||D


2 commentaires

Pourquoi pas simplement ss.replaceAll ("\\ +", "||") ?


@ernest_k Il peut y avoir de telles alternatives, mais je tiens à savoir pourquoi cela ne fonctionne pas ..!


3 Réponses :


2
votes

Vous pouvez simplement utiliser:

String ss = "A+B+C+D";
Matcher mm = Pattern.compile("\\+").matcher(ss);

StringBuffer sb = new StringBuffer();

while (mm.find()) {
    mm.appendReplacement(sb, "||");
}
mm.appendTail(sb);

System.out.println(sb);

comme @ernest_k l'a souligné. Si vous voulez vraiment continuer à utiliser un matcher avec itération, utilisez Matcher # appendReplacement avec un StringBuffer:

ss = ss.replaceAll("\\+", "||")

p >


2 commentaires

Merci @Tim, je me demande simplement pourquoi les sélecteurs de groupe ne fonctionnent pas de la même manière?


@Pratik Tout d'abord $ 1 et $ 2 etc. ne sont disponibles que dans le deuxième paramètre de remplacement par String # replaceAll . L'approche que vous adoptez n'a pas beaucoup de sens, car la boucle signifie que vous itérez sur l'entrée et que replaceAll est encore en train d'itérer. Suivez le modèle que j'ai donné dans la deuxième partie de ma réponse si vous voulez itérer avec un modèle regex.



0
votes

Je pense que nous aurions peut-être besoin d'une simple chaîne de remplacement:

Démo

Test

import java.util.regex.Matcher;
import java.util.regex.Pattern;

final String regex = "\\+";
final String string = "A+B+C+D";
final String subst = "||";

final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
final Matcher matcher = pattern.matcher(string);
final String result = matcher.replaceAll(subst);

System.out.println(result);

Ce lien sur le panneau de droite explique votre expression originale. Le premier groupe de capture correspond entre un et des temps illimités, autant de fois que possible, donc cela ne fonctionnerait pas ici. Si nous les avions changés en (. +?) , cela aurait partiellement fonctionné, mais toujours inutile.


1 commentaires

Merci @Emma, ​​je me demande simplement pourquoi les sélecteurs de groupe ne fonctionnent pas de la même manière?



1
votes

La raison pour laquelle vous ne remplacez qu'un seul élément est que vous correspondez à la ligne entière. L'expression régulière que vous utilisez "(? Imc) (. +) \\ s * \\ + \\ s * (. +)" correspond à tout ce qui est (. +) Code > jusqu'à la fin, puis revient pour qu'il puisse correspondre au reste \\ s * \\ + ... . Donc, fondamentalement, votre groupe 1 est. + Presque tout, mais le dernier + et au-delà. Par conséquent, replaceAll ne peut correspondre qu'une seule fois et se terminera après ce remplacement. Ce dont vous avez besoin est un remplacement qui trouve + éventuellement entouré d'espaces:

Pattern.compile("(?imc)\\s*\\+\\s*");

Cela doit correspondre à tout ce que vous voulez faire correspondre, et ne correspond pas à la ligne entière, mais uniquement votre personnage de remplacement.


1 commentaires

Merci @TreffnonX. Cela clarifie la confusion :)