正则表达式只替换内部标记(需要帮助编写正则表达式)

时间:2013-02-08 08:45:45

标签: java regex

我需要编写正则表达式,将a替换为b,但仅限于<pre>标记内。

实施例

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

结果

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

请帮助编写java String.replace函数的表达式。保证pre标签不嵌套。

3 个答案:

答案 0 :(得分: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>部分之外进行匹配。通过此更改,我们不需要*?量词,并且可以使用更常见的“贪婪”(*)量词。这开始看起来很像我的另一个答案,我真的只是一个笑话!)

你最好使用Matcher(关注我的代码):

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></pre>不匹配。

答案 1 :(得分:0)

这是一个可以完成这项任务的正则表达式(我认为:我不会过多地投注它通过所有测试enter image description here

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>就可以找到它。

答案 2 :(得分:-1)

Pattern pattern = Pattern.compile("<pre>(.+?)</pre>");
java.util.regex.Matcher matcher = pattern.matcher("a <pre> c a <tag> a d </pre> a");

试试这个: