1

我需要编写替换ab但仅在<pre>标签内的正则表达式。

例子

a <pre> c a <foo> a d </pre> a

结果

a <pre> c b <foo> b d </pre> a

请帮助编写javaString.replace函数的表达式。保证pre标签没有嵌套。

4

3 回答 3

3

我认为你可以用 String.replace() 做的最好的事情是:

String string = ...
for (;;)
{
    String original = string;
    string = string.replaceFirst("(<pre>.*?)a(.*?</pre>)", "$1b$2");
    if (original.equals(string))
        break;
}

编辑:@Bohemian 已经注意到上述正则表达式无法正常工作。因此需要将其更改为:(
(<pre>(?:(?!</pre>).)*a((?:(?!<pre>).)*</pre>)未经测试)以避免在部分之外匹配<pre>...</pre>。通过此更改,我们不需要*?量词并且可以使用更多常见的“贪婪”(*)量词。这开始看起来很像我的其他答案,我只是开玩笑!)

你最好使用匹配器(按照我脑海中的代码):

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

Pattern pattern = Pattern.compile("(?<=<pre>)(.*?)(?=</pre>)");
Matcher m = pattern.matcher(string);
StringBuffer replacement = new StringBuffer();

while (matcher.find())
{
     matcher.appendReplacement(replacement, "");
     // Careful using unknown text in appendReplacement as any "$n" will cause problems
     replacement.append(matcher.group(1).replace("a", "b"));
}    
matcher.appendTail(replacement);
String result = replacement.toString();

编辑:更改了上面的模式,使其与周围<pre>的 and不匹配</pre>

于 2013-02-08T09:23:58.303 回答
0

这是一个可以完成这项工作的正则表达式(我认为:我不会在它通过所有测试方面下太多赌注在此处输入图像描述

String replacement = original.replaceAll(
    "(?<=<pre>(?:(?!</pre>).){0,50})a(?=(?:(?!<pre>).)*</pre>)", 
    "b");

解释:

  • (?<=<pre>(?:(?!</pre>).){0,50})- <pre>只要我们不回头</pre>找到它,就向后看。Java 需要有限的最大长度后视,所以我们使用{0,50}而不是*.
  • a- 我们要替换的字符
  • (?=(?:.(?!<pre>))*</pre>)- 向前看,</pre>只要我们不穿越过去<pre>就可以找到它。
于 2013-02-08T09:57:07.000 回答
-1
Pattern pattern = Pattern.compile("<pre>(.+?)</pre>");
java.util.regex.Matcher matcher = pattern.matcher("a <pre> c a <tag> a d </pre> a");

试试这个:

于 2013-02-08T09:23:23.510 回答