0

私は次のようなパターンを持っています:<[a-zA-Z][^>]*(?:poster|src)=(['\"])([^'\"]+)\\1[^>]*> ここでは、src または poster 属性の値を置き換えたいと思います。

大丈夫です

<video src='srcVal' />

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

しかし、

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

matcher.group(2)のみを返すため、src 値のみを変更します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 つの先読みを使用しています。先読みにより、何が先に来るかを 2 回確認できるため、順序は無視されます。ただし、これらの先読みは常に機能する必要があります (それを確認するために * と ? を使用します)。それらをキャッチします。.*?a?常に何もキャッチしません。そこで、ここで を使用します(?:.*?a)?。ここでの動作は、怠惰にaをキャッチしようとすることですが、失敗しても問題ありません。
正規表現の最後の部分は、poster または src 属性を持つタグのみを確実にキャッチするようにすることです。

とにかく役に立たなかったので、属性のチェックを削除したことに注意してください。

于 2013-04-03T15:53:18.723 に答える