简体   繁体   English

正则表达式替换两组

[英]regular expression replace two group

I have pattern like : <[a-zA-Z][^>]*(?:poster|src)=(['\\"])([^'\\"]+)\\\\1[^>]*> here i want to replace the value of src or poster attributes. 我有这样的模式: <[a-zA-Z][^>]*(?:poster|src)=(['\\"])([^'\\"]+)\\\\1[^>]*>在这里,我想替换src或poster属性的值。

It is okey for 这是对的

<video src='srcVal' />

and

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

but for 但对于

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

only changes src value, due to matcher.group(2) returning only srcVal . 由于matcher.group(2)仅返回srcVal ,因此仅更改src值。

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

Does any body has an idea how to do this? 有没有人知道如何做到这一点?

The basic problem is with the [^>]* near the start of your expression. 基本问题是表达式开头附近的[^>]* Because * is greedy this will eat up as many characters as it can while still allowing the rest of the expression to match, so given 因为*是贪婪的,这会吃掉尽可能多的字符,同时仍然允许表达式的其余部分匹配,因此给定

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

the [^>]* will gobble ideo poster='posterVal' up to and including the space before src= . [^>]*将使ideo poster='posterVal'吞噬直至src=之前的空格。

I would approach it differently, rather than trying to write a regex that matches the whole tag just write one that matches the attributes you're interested in, and replace all matches of that expression 我会采取不同的方法,而不是尝试编写与整个标签匹配的正则表达式,而只是编写与您感兴趣的属性匹配的正则表达式,然后替换该表达式的所有匹配项

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

But as other posters have commented it would be much more sensible to use a proper parser that understands the language rather than trying to manipulate the textual representation with regular expressions. 但是,正如其他张贴者所评论的那样,使用一种能够理解该语言的适当解析器,而不是尝试使用正则表达式来操纵文本表示,会更加明智。

I wouldn't do this with regex, but you can try such a thing: 我不会使用正则表达式来执行此操作,但是您可以尝试以下操作:

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

Though I don't have time to test it as of now, sorry. 尽管到目前为止我还没有时间进行测试,对不起。

Edit: 编辑:
Less performance-oriented: 不太注重性能:

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

If you only want to match video tags, change it to (as it'd greatly improve it): 如果您只想匹配视频标签,请将其更改为(这将大大改善它):

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

Explanation: (as I guess it must look quite disturbing) 说明:(因为我想它看起来一定很令人不安)

We're using 2 lookaheads to capture what's interesting. 我们正在使用2个前瞻记录来捕获有趣的内容。 Lookaheads will allow us to check twice what comes ahead, therefore ignoring the order. 先行者将使我们能够检查两次即将发生的事情,因此忽略了顺序。 However, those lookaheads must always work (using * and ? to make sure of that), but still being greedy, while being lazy (what?): we have to stop as soon as we see poster/src, but go far enough to catch those. 但是,这些前瞻必须始终有效(使用*和?来确保这一点),但仍要保持贪婪,同时要保持懒惰(是什么?):看到海报/ src后,我们必须立即停止,但要走得足够远抓住那些。 .*?a? will always catch nothing. 永远一无所获。 So we use here (?:.*?a)? 所以我们在这里使用(?:.*?a)? . The behavior here is to try to catch the a with laziness, while if it fails it's not a problem. 这里的行为是尝试以懒惰的方式捕获a ,而如果失败则不成问题。
The last part of the regex is to make sure we catch only tags with a poster or a src attribute, as our lookaheads only do that catching and certainly can't be used to do that. 正则表达式的最后一部分是确保我们仅捕获带有发帖人或src属性的标签,因为我们的先行者只会捕获该对象,并且肯定不能用来捕获它。

Note that I removed the check for your attributes, as anyway it was useless. 请注意,我删除了对您的属性的检查,因为无论如何它都没有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM