正则表达式取代两组

时间:2013-04-03 15:36:55

标签: java regex replace

我的模式如下:<[a-zA-Z][^>]*(?:poster|src)=(['\"])([^'\"]+)\\1[^>]*> 这里我想替换src或poster属性的值。

这是

<video src='srcVal' />

<video poster='posterVal' src='srcVal' />

但是

<video poster='posterVal' src='srcVal' />

仅更改src值,因为matcher.group(2)仅返回srcVal

public class Test {
    public static void main(String[] args) throws Exception {
        String html = "<video poster='posterVal' src='srcVal' />";
        Pattern resourcePattern = Pattern.compile("<[a-zA-Z][^>]*(?:poster|src)=(['\"])([^'\"]+)\\1[^>]*>");
        Matcher matcher = resourcePattern.matcher(html);
        int last = 0;
        StringBuilder sb = new StringBuilder();
        while(matcher.find()) {
            String path = matcher.group(2) + "Changed";
            sb.append( html.substring(last, matcher.start(2)) + path );
            last = matcher.end(2);
        }
        sb.append(html.substring(last));
        System.out.println(sb);
        //outputs <video poster='posterVal' src='srcValChanged' />
        //expecting <video poster='posterValChanged' src='srcValChanged' />
    }
}

有没有人知道如何做到这一点?

2 个答案:

答案 0 :(得分:0)

基本问题是表达式开头附近的[^>]*。因为*是贪婪的,所以这会占用尽可能多的字符,同时仍然允许表达式的其余部分匹配,所以给定

<video poster='posterVal' src='srcVal' />

[^>]*会吞噬ideo poster='posterVal'直至并包括src=之前的空格。

我会以不同的方式处理它,而不是尝试编写与整个标记匹配的正则表达式,只需编写一个与您感兴趣的属性相匹配的正则表达式,并替换该表达式的所有匹配

html.replaceAll("\\b((?:poster|src)=)(['\"])([^'\"]+)\\1", "$1$2$3Changed$2")

但正如其他海报所评论的那样,使用理解语言的正确解析器而不是试图用正则表达式操纵文本表示会更加明智。

答案 1 :(得分:0)

我不会用正则表达式来做这件事,但你可以尝试这样的事情:

<[a-zA-Z]*[^>]*(?:(poster)|src)=(['\"])([^'\"]+)\\2(?(1)[^>]*(?:src=(['\"])([^'\"]+)\\4)?[^>]*|[^>]*(?:poster=(['\"])([^'\"]+)\\6)?[^>]*)>

虽然我现在没时间测试它,抱歉。

修改
不太注重绩效:

<[a-zA-Z]*(?=(?:[^>]*?poster=['\"]([^'\"]+))?)(?=(?:[^>]*?src=['\"]([^'\"]+))?)[^>]*(?:poster|src)[^>]*>

如果您只想匹配视频代码,请将其更改为(因为它会大大改善它):

<video(?=(?:[^>]*?poster=['\"]([^'\"]+))?)(?=(?:[^>]*?src=['\"]([^'\"]+))?)[^>]*(?:poster|src)[^>]*>

说明:(因为我觉得它看起来一定很令人不安)

我们正在使用2个前瞻来捕捉有趣的内容。 Lookaheads将允许我们检查两次未来的事情,因此无视订单。然而,那些前瞻必须始终有效(使用*和?确保这一点),但仍然贪婪,而懒惰(什么?):我们必须在看到poster / src时立即停止,但是要走得足够远赶上那些。 .*?a?总会一无所获。我们在这里使用(?:.*?a)?。这里的行为是试图用懒惰来抓住 a ,而如果它失败则不是问题。
正则表达式的最后一部分是确保我们只捕获带有海报或src属性的标签,因为我们的前瞻只会捕捉并且肯定无法用来做到这一点。

请注意,我删除了对您的属性的检查,因为它无论如何都没用。