如何在 java 中使用正则表达式替换标签 <> 中所有出现的字符串
how to replace all occurrences of a string inside tags <> using regex in java
我在标签中有一个字符串。例如:“我是 src scr 客户”
我想用“abc”替换“src”。我使用以下正则表达式来替换:-
replacAll("(.?)src(.?)"),"$1"+"abc"+"$2");
但它仅替换第一次出现的字符串,即输出为“I am abc src customer”
我希望输出为“我是 abc abc 客户”。
我不想使用匹配器模式。有没有使用 replaceAll() 的解决方案?请帮忙。
我们可以在这里尝试使用正式的正则表达式模式匹配器。匹配模式 <abc~a>(.*?)<abc~a>
,并为每个匹配附加标签,其中 src
替换为 abc
。这是一个示例代码:
String input = "Here is a src <abc~a>I am an src customer<abc~b> also another src here.";
Pattern p = Pattern.compile("<abc~a>(.*?)<abc~b>");
Matcher m = p.matcher(input);
StringBuffer buffer = new StringBuffer();
while(m.find()) {
String replace = "<abc~a>" + m.group(1).replaceAll("\bsrc\b", "abc") + "<abc~b>";
m.appendReplacement(buffer, replace);
}
m.appendTail(buffer);
System.out.println(buffer.toString());
这会打印:
Here is a src <abc~a>I am an abc customer<abc~b> also another src here.
请注意,在许多其他语言中,我们可以使用正则表达式回调函数。但是核心 Java 不支持这个功能,所以我们必须遍历整个输入。
当您使用 Java 9 或更新版本时,解决问题的最简单方法是
Pattern p = Pattern.compile("(?<=<abc~a>).*?(?=<abc~b>)");
String result = p.matcher(input)
.replaceAll(m -> m.group().replaceAll("\bsrc\b", "abc"));
基本上,它在幕后与 相同。细微差别是它将使用 StringBuilder
而不是 StringBuffer
,该选项仅在 Java 9 之后可用,如果外部模式不匹配,它将 return 原始字符串实例(p
) 已找到(而不是副本)。
我还改变了模式使用look-behind和look-ahead,这简化了替换功能,也减少了字符复制量。
请注意,两个 replaceAll
操作具有相似的 appendReplacement
loop behind the scenes. The method appendReplacement
will search for replacement patterns (e.g. $number
) in the replacement string, which does not only apply to "abc"
but also the entire group between the <abc~a>
and <abc~b>
tag. If you can’t preclude the presence of conflicting special characters, you have to use Matcher.quoteReplacement
以避免出现问题。
除了不需要的替换模式解释外,内部 replaceAll
会在每次调用时将模式字符串 compile 转换为 Pattern
对象。此外,内部操作创建了一个临时字符串,然后用于外部替换操作,因此这个简单的解决方案将多次复制一些字符内容。
如果性能真的很重要,那么写一个专门的操作是值得的,即使它更冗长。
static final Pattern OUTER_PATTERN = Pattern.compile("<abc~a>(.*?)<abc~b>");
static final Pattern INNER_PATTERN = Pattern.compile("\bsrc\b");
String replacement = "abc";
String result;
Matcher m = OUTER_PATTERN.matcher(input);
if(!m.find()) result = input;
else {
StringBuilder sb = new StringBuilder(input.length());
int copyStart = 0, nextSearchStart;
do {
nextSearchStart = m.end();
for(m.region(m.start(1), m.end(1)).usePattern(INNER_PATTERN);
m.find(); copyStart = m.end()) {
sb.append(input, copyStart, m.start()).append(replacement);
}
} while(m.region(nextSearchStart, input.length()).usePattern(OUTER_PATTERN).find());
result = copyStart==0? input: sb.append(input, copyStart, input.length()).toString();
}
这不会多次编译模式,而是在没有中间步骤的单个替换操作中使用两种模式,执行必要的最少字符复制。替换字符串使用 StringBuilder.append
按字面复制,因此不需要引号。与内置 replaceAll
一样,当未找到外部模式的匹配项时,它将 return 原始字符串。但当外部模式匹配但受影响区域内没有内部模式匹配时,它也会 return 原始字符串。
我在标签中有一个字符串。例如:“
我想用“abc”替换“src”。我使用以下正则表达式来替换:-
replacAll("(
我希望输出为“
我不想使用匹配器模式。有没有使用 replaceAll() 的解决方案?请帮忙。
我们可以在这里尝试使用正式的正则表达式模式匹配器。匹配模式 <abc~a>(.*?)<abc~a>
,并为每个匹配附加标签,其中 src
替换为 abc
。这是一个示例代码:
String input = "Here is a src <abc~a>I am an src customer<abc~b> also another src here.";
Pattern p = Pattern.compile("<abc~a>(.*?)<abc~b>");
Matcher m = p.matcher(input);
StringBuffer buffer = new StringBuffer();
while(m.find()) {
String replace = "<abc~a>" + m.group(1).replaceAll("\bsrc\b", "abc") + "<abc~b>";
m.appendReplacement(buffer, replace);
}
m.appendTail(buffer);
System.out.println(buffer.toString());
这会打印:
Here is a src <abc~a>I am an abc customer<abc~b> also another src here.
请注意,在许多其他语言中,我们可以使用正则表达式回调函数。但是核心 Java 不支持这个功能,所以我们必须遍历整个输入。
当您使用 Java 9 或更新版本时,解决问题的最简单方法是
Pattern p = Pattern.compile("(?<=<abc~a>).*?(?=<abc~b>)");
String result = p.matcher(input)
.replaceAll(m -> m.group().replaceAll("\bsrc\b", "abc"));
基本上,它在幕后与 StringBuilder
而不是 StringBuffer
,该选项仅在 Java 9 之后可用,如果外部模式不匹配,它将 return 原始字符串实例(p
) 已找到(而不是副本)。
我还改变了模式使用look-behind和look-ahead,这简化了替换功能,也减少了字符复制量。
请注意,两个 replaceAll
操作具有相似的 appendReplacement
loop behind the scenes. The method appendReplacement
will search for replacement patterns (e.g. $number
) in the replacement string, which does not only apply to "abc"
but also the entire group between the <abc~a>
and <abc~b>
tag. If you can’t preclude the presence of conflicting special characters, you have to use Matcher.quoteReplacement
以避免出现问题。
除了不需要的替换模式解释外,内部 replaceAll
会在每次调用时将模式字符串 compile 转换为 Pattern
对象。此外,内部操作创建了一个临时字符串,然后用于外部替换操作,因此这个简单的解决方案将多次复制一些字符内容。
如果性能真的很重要,那么写一个专门的操作是值得的,即使它更冗长。
static final Pattern OUTER_PATTERN = Pattern.compile("<abc~a>(.*?)<abc~b>");
static final Pattern INNER_PATTERN = Pattern.compile("\bsrc\b");
String replacement = "abc";
String result;
Matcher m = OUTER_PATTERN.matcher(input);
if(!m.find()) result = input;
else {
StringBuilder sb = new StringBuilder(input.length());
int copyStart = 0, nextSearchStart;
do {
nextSearchStart = m.end();
for(m.region(m.start(1), m.end(1)).usePattern(INNER_PATTERN);
m.find(); copyStart = m.end()) {
sb.append(input, copyStart, m.start()).append(replacement);
}
} while(m.region(nextSearchStart, input.length()).usePattern(OUTER_PATTERN).find());
result = copyStart==0? input: sb.append(input, copyStart, input.length()).toString();
}
这不会多次编译模式,而是在没有中间步骤的单个替换操作中使用两种模式,执行必要的最少字符复制。替换字符串使用 StringBuilder.append
按字面复制,因此不需要引号。与内置 replaceAll
一样,当未找到外部模式的匹配项时,它将 return 原始字符串。但当外部模式匹配但受影响区域内没有内部模式匹配时,它也会 return 原始字符串。