我有一个变量 v ,它可能在字符串中连续出现多次。我想这样做,以便所有连续的 v 变成一个 v 。例如:
String s = "Hello, world!";
String v = "l";
正则表达式会变成“Hello,world!”进入“Helo,世界!”
所以我想做一些像
这样的事情s = s.replaceAll(vv+, v)
但显然这不起作用。想法?
答案 0 :(得分:17)
让我们迭代地开发解决方案;在每一步中,我们都会指出问题是什么,并在我们得出最终答案之前加以解决。
我们可以从这样的事情开始:
String s = "What???? Impo$$ible!!!";
String v = "!";
s = s.replaceAll(v + "{2,}", v);
System.out.println(s);
// "What???? Impo$$ible!"
{2,}
是有限重复的正则表达式语法,在这种情况下意味着“至少2”。
上述情况恰好如此,因为!
不是正则表达式元字符。让我们看看如果我们尝试以下内容会发生什么:
String v = "?";
s = s.replaceAll(v + "{2,}", v);
// Exception in thread "main" java.util.regex.PatternSyntaxException:
// Dangling meta character '?'
解决问题的一种方法是使用Pattern.quote
,以便v
按字面意思理解:
s = s.replaceAll(Pattern.quote(v) + "{2,}", v);
System.out.println(s);
// "What? Impo$$ible!!!"
事实证明,这不是我们唯一需要担心的事情:在替换字符串中,\
和$
也是特殊的元字符。这就解释了为什么我们会遇到以下问题:
String v = "$";
s = s.replaceAll(Pattern.quote(v) + "{2,}", v);
// Exception in thread "main" java.lang.StringIndexOutOfBoundsException:
// String index out of range: 1
由于我们希望将v
字面上作为替换字符串,因此我们使用Matcher.quoteReplacement
,如下所示:
s = s.replaceAll(Pattern.quote(v) + "{2,}", Matcher.quoteReplacement(v));
System.out.println(s);
// "What???? Impo$ible!!!"
最后,重复的优先级高于连接。这意味着以下内容:
System.out.println( "hahaha".matches("ha{3}") ); // false
System.out.println( "haaa".matches("ha{3}") ); // true
System.out.println( "hahaha".matches("(ha){3}") ); // true
因此,如果v
可以包含多个字符,那么您需要在应用重复之前对其进行分组。在这种情况下,您可以使用非捕获组,因为您不需要创建反向引用。
String s = "well, well, well, look who's here...";
String v = "well, ";
s = s.replaceAll("(?:" +Pattern.quote(v)+ "){2,}", Matcher.quoteReplacement(v));
System.out.println(s);
// "well, look who's here..."
Pattern.quote
Matcher.quoteReplacement
以下示例使用不情愿的重复,捕获组和反向引用以及不区分大小写的匹配:
System.out.println(
"omgomgOMGOMG???? Yes we can! YES WE CAN! GOAAALLLL!!!!"
.replaceAll("(?i)(.+?)\\1+", "$1")
);
// "omg? Yes we can! GOAL!"
答案 1 :(得分:5)
使用x{2,}
至少匹配x
两次。
为了能够替换正则表达式具有特殊含义的字符,您可以使用Pattern.quote
:
String part = Pattern.quote(v);
s = s.replaceAll(part + "{2,}", v);
要替换长于一个字符的内容,请使用非捕获组:
String part = "(?:" + Pattern.quote(v) + ")";
s = s.replaceAll(part + "{2,}", v);
答案 2 :(得分:4)
你需要连接两个“v”字符串。
尝试s = s.replaceAll(v + v + "+", v)
答案 3 :(得分:3)
使用Java中的正则表达式确保使用Pattern.quote和Matcher.quoteReplacement:
package com.example.test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex2 {
static public void main(String[] args)
{
String s = "Hello, world!";
String v = "l";
System.out.println(doit(s,v));
s = "Test: ??r??r Solo ??r Frankenstein!";
v = "??r";
System.out.println(doit(s,v));
}
private static String doit(String s, String v)
{
Pattern p = Pattern.compile("(?:"+Pattern.quote(v)+"){2,}");
Matcher m = p.matcher(s);
StringBuffer sb = new StringBuffer();
while (m.find())
{
m.appendReplacement(sb, Matcher.quoteReplacement(v));
}
m.appendTail(sb);
return sb.toString();
}
}
答案 4 :(得分:2)
s = s.replaceAll (v + "+", v)