0

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

没关系

<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' />
    }
}

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

4

2 回答 2

0

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

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

[^>]*吞噬ideo poster='posterVal'并包括之前的空间src=

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

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

但正如其他发帖人所评论的那样,使用理解语言的适当解析器而不是尝试使用正则表达式来操纵文本表示会更明智。

于 2013-04-03T15:49:55.570 回答
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 将允许我们检查两次前面的内容,因此忽略顺序。但是,这些前瞻必须始终有效(使用 * 和 ? 来确保这一点),但仍然是贪婪的,同时又是懒惰的(什么?):我们必须在看到海报/src 时立即停止,但要走得足够远抓住那些。.*?a?总是什么也抓不到。所以我们在这里使用(?:.*?a)?. 这里的行为是尝试用懒惰来捕捉a,而如果它失败了,这不是问题。
正则表达式的最后一部分是确保我们只捕获带有海报或 src 属性的标签,因为我们的前瞻只做那个捕获,当然不能用来做那个。

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

于 2013-04-03T15:53:18.723 回答