替换第 1 组 Java 正则表达式而不替换整个正则表达式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38296673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replace group 1 of Java regex with out replacing the entire regex
提问by Aditya
I have a regex pattern that will have only one group. I need to find texts in the input strings that follows the pattern and replace ONLY the match group 1. For example I have the regex pattern and the string to be applied on as shown below. The replacement string is "<---->"
我有一个只有一组的正则表达式模式。我需要在输入字符串中找到遵循模式的文本并仅替换匹配组 1。例如,我有正则表达式模式和要应用的字符串,如下所示。替换字符串为“<---->”
Pattern p = Pattern.compile("\w*(lan)\w+");
Matcher m = p.matcher("plan plans lander planitia");
The expected result is
预期的结果是
plan p<--->s <--->der p<--->itia
I tried following approaches
我尝试了以下方法
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);
This gives result as
这给出了结果
p<---> p<--->s <--->der p<--->itia
Another approach
另一种方法
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);
Result is
结果是
plan <---> <---> <--->
I have gone through thislink. Here the part of the string before the match is always constant and is "foo" but in my case it varies. Also I have looked at thisand thisbut I am unable to apply any on the solutions given to my present scenario.
我已经通过这个链接。这里匹配之前的字符串部分始终是常量并且是“foo”,但在我的情况下它会有所不同。我也看过这个和这个,但我无法将任何应用于我当前场景的解决方案。
Any help is appreciated
任何帮助表示赞赏
采纳答案by Wiktor Stribi?ew
You need to use the following pattern with capturing groups:
您需要对捕获组使用以下模式:
(\w*)lan(\w+)
^-1-^ ^-2-^
and replace with $1<--->$2
并替换为 $1<--->$2
See the regex demo
查看正则表达式演示
The point is that we use a capturing group around the parts that we want to keep and just match what we want to discard.
关键是我们在我们想要保留的部分周围使用了一个捕获组,并且只匹配我们想要丢弃的部分。
String str = "plan plans lander planitia";
System.out.println(str.replaceAll("(\w*)lan(\w+)", "<--->"));
// => plan p<--->s <--->der p<--->itia
If you need to be able to replace the Group 1 and keep the rest, you may use the replace callback method emulation with Matcher#appendReplacement
:
如果您需要能够替换第 1 组并保留其余部分,您可以使用替换回调方法模拟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
Here, since we process a match by match, we should only replace the Group 1 contents once with replaceFirst
, and since we replace the substring as a literal, we should Pattern.quote
it.
在这里,由于我们逐个处理匹配,我们应该只用 替换 Group 1 的内容一次replaceFirst
,并且由于我们将子字符串替换为文字,我们应该Pattern.quote
这样做。
回答by Sebastian Proske
While Wiktors explanation of the use of capturing groups is completely correct, you could avoid using them at all. The \\w*
at the start of your pattern seems irrelevant, as you want to keep it anyways, so we can simply leave it out of the pattern. The check for a word-character after lan
can be done using a lookahead, like (?=\w)
, so we actually only match lan
in a pattern like "lan(?=\\w)"
and can do a simple replace with "<--->"
(or whatever you like).
虽然 Wiktor 对使用捕获组的解释是完全正确的,但您完全可以避免使用它们。在\\w*
你的模式的开头似乎无关紧要,只要你想保持它反正,所以我们可以简单地把它从格局。之后的单词字符检查lan
可以使用前瞻来完成,比如(?=\w)
,所以我们实际上只匹配lan
一个模式 like"lan(?=\\w)"
并且可以做一个简单的替换"<--->"
(或任何你喜欢的)。
回答by Andreas
To dynamically control the replacement value, use a find()
loop with appendReplacement()
, finalizing the result with appendTail()
.
要动态控制替换值,请使用find()
with 循环,用appendReplacement()
结束结果appendTail()
。
That way you have full control of the replacement value. In your case, the pattern is the following, and you can get the positions indicated.
这样您就可以完全控制替换值。在您的情况下,模式如下,您可以获得指示的位置。
start(1)
↓ end(1)
↓ ↓
\w*(lan)\w+
↑ ↑
start() end()
You can then extract the values to keep.
然后,您可以提取要保留的值。
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);
Output
输出
plan p<--->s <--->der p<--->itia
If you don't like that it uses the original string, you can use the matched substring instead.
如果您不喜欢它使用原始字符串,您可以使用匹配的子字符串。
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();
回答by Ond?ej Men?l
I like others solutions. This is slightly optimalised bulletproof version:
我喜欢其他解决方案。这是稍微优化的防弹版本:
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"
}