J'ai un motif de regex qui aura un seul groupe. Je dois trouver des textes dans les chaînes d'entrée qui suivent le modèle et remplacer UNIQUEMENT le groupe de correspondance 1. Par exemple, j'ai le modèle d'expression régulière et la chaîne à appliquer, comme indiqué ci-dessous. La chaîne de remplacement est "<---->"
Pattern p = Pattern.compile("\\w*(lan)\\w+");
Matcher m = p.matcher("plan plans lander planitia");
Le résultat attendu est
plan p<--->s <--->der p<--->itia
J'ai essayé de suivre les approches
String test = "plan plans lander planitia";
Pattern p = Pattern.compile("\\w*(lan)\\w+");
Matcher m = p.matcher(test);
String result = "";
while(m.find()){
result = test.replaceAll(m.group(1),"<--->");
}
System.out.print(result);
Cela donne comme résultat
p<---> p<--->s <--->der p<--->itia
Une autre approche
String test = "plan plans lander planitia";
Pattern p = Pattern.compile("\\w*(lan)\\w+");
Matcher m = p.matcher(test);
String result = "";
while(m.find()){
result = test.replaceAll("\\w*(lan)\\w+","<--->");
}
System.out.print(result);
Le résultat est
plan <---> <---> <--->
J'ai traversé this link. Ici la partie de la chaîne avant la correspondance est toujours constante et est "foo" mais dans mon cas, elle varie. J'ai aussi regardé ceci et ceci mais je suis incapable d'appliquer les solutions apportées à mon scénario actuel.
Toute aide est appréciée
Vous devez utiliser le modèle suivant pour capturer des groupes:
(\w*)lan(\w+)
^-1-^ ^-2-^
et remplacez par $1<--->$2
Voir la démo regex _
Le fait est que nous utilisons un groupe de capture autour des parties que nous voulons conserver et que nous ne faisons que correspondre à ce que nous voulons rejeter.
String str = "plan plans lander planitia";
System.out.println(str.replaceAll("(\\w*)lan(\\w+)", "$1<--->$2"));
// => plan p<--->s <--->der p<--->itia
Si vous devez pouvoir remplacer le groupe 1 et conserver le reste, vous pouvez utiliser l'émulation de la méthode de rappel de remplacement avec Matcher#appendReplacement
:
String text = "plan plans lander planitia";
String pattern = "\\w*(lan)\\w+";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(text);
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, m.group(0).replaceFirst(Pattern.quote(m.group(1)), "<--->"));
}
m.appendTail(sb); // append the rest of the contents
System.out.println(sb.toString());
// output => plan p<--->s <--->der p<--->itia
Voir une autre démo Java
Ici, puisque nous traitons une correspondance, nous ne devrions remplacer le contenu du groupe 1 qu'une seule fois par replaceFirst
, et puisque nous remplaçons la sous-chaîne en tant que littéral, nous devrions Pattern.quote
le.
Pour contrôler dynamiquement la valeur de remplacement, utilisez un find()
boucle avec appendReplacement()
, en finalisant le résultat avec appendTail()
.
De cette façon, vous avez le plein contrôle de la valeur de remplacement. Dans votre cas, le motif est le suivant et vous pouvez obtenir les positions indiquées.
start(1)
↓ end(1)
↓ ↓
\\w*(lan)\\w+
↑ ↑
start() end()
Vous pouvez ensuite extraire les valeurs à conserver.
String input = "plan plans lander planitia";
StringBuffer buf = new StringBuffer();
Matcher m = Pattern.compile("\\w*(lan)\\w+").matcher(input);
while (m.find())
m.appendReplacement(buf, input.substring(m.start(), m.start(1)) +
"<--->" +
input.substring(m.end(1), m.end()));
String output = m.appendTail(buf).toString();
System.out.println(output);
Sortie
plan p<--->s <--->der p<--->itia
Si vous n'aimez pas le fait qu'il utilise la chaîne d'origine, vous pouvez utiliser la sous-chaîne correspondante à la place.
StringBuffer buf = new StringBuffer();
Matcher m = Pattern.compile("\\w*(lan)\\w+").matcher("plan plans lander planitia");
while (m.find()) {
String match = m.group();
int start = m.start();
m.appendReplacement(buf, match.substring(0, m.start(1) - start) +
"<--->" +
match.substring(m.end(1) - start, m.end() - start));
}
String output = m.appendTail(buf).toString();
Bien que l'explication de Wiktors sur l'utilisation des groupes de capture soit tout à fait correcte, vous pouvez éviter de les utiliser du tout. Le \\w*
au début de votre modèle ne semble pas être pertinent, car vous souhaitez le conserver de toute façon, afin que nous puissions simplement le laisser en dehors du modèle. La vérification d'un caractère Word après lan
peut être effectuée à l'aide d'un lookahead, tel que (?=\w)
, de sorte que nous ne correspondons que lan
dans un modèle tel que "lan(?=\\w)"
et que nous pouvons simplement remplacer par "<--->"
(ou ce que vous voudrez).
J'aime les autres solutions. Il s'agit d'une version à l'épreuve des balles légèrement optimisée:
public static void main (String [] args) {
int groupPosition = 1;
String replacement = "foo";
Pattern r = Pattern.compile("foo(bar)");
Matcher m = r.matcher("bar1234foobar1234bar");
StringBuffer sb = new StringBuffer();
while (m.find()) {
StringBuffer buf = new StringBuffer(m.group());
buf.replace(m.start(groupPosition)-m.start(), m.end(groupPosition)-m.start(), replacement);
m.appendReplacement(sb, buf.toString());
}
m.appendTail(sb);
System.out.println(sb.toString()); // result is "bar1234foofoo1234bar"
}