我需要编写正则表达式,将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
标签不嵌套。
答案 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)
这是一个可以完成这项任务的正则表达式(我认为:我不会过多地投注它通过所有测试)
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");
试试这个: