0

コンテンツに存在するすべての画像の src と残りの属性を取得するための正規表現があります。

<img *((.|\s)*?) *src *= *['"]([^'"]*)['"] *((.|\s)*?) */*>

照合しているコンテンツが次のような場合

<img src=src1"/> <img src=src2"/>

find(index) がハングし、スレッド ダンプに次のように表示されます

at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4357)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
    at java.util.regex.Pattern$BranchConn.match(Pattern.java:4078)
    at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345)
    at java.util.regex.Pattern$Branch.match(Pattern.java:4114)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
    at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4357)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
    at java.util.regex.Pattern$BranchConn.match(Pattern.java:4078)
    at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345)
    at java.util.regex.Pattern$Branch.match(Pattern.java:4114)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
    at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4357)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
    at java.util.regex.Pattern$BranchConn.match(Pattern.java:4078)
    at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345)
    at java.util.regex.Pattern$Branch.match(Pattern.java:4114)
    at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
    at java.util.regex.Pattern$LazyLoop.match(Pattern.java:4357)
    at java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
    at java.util.regex.Pattern$BranchConn.match(Pattern.java:4078)
    at java.util.regex.Pattern$CharProperty.match(Pattern.java:3345) 

この問題を解決するための解決策または回避策はありますか?

4

2 に答える 2

0

あなたが持っているのは「悪の正規表現」のようです。これは、あるもの (src) を別のもの (img) 内で一致させるために複雑な正規表現を構築しようとするときに珍しくありません。特に、 で行っている複雑な部分式に繰り返しを適用しようとすると、通常、邪悪な正規表現が発生します(.|\s)*?

より良いアプローチは、2 つの正規表現を使用することです。1 つはすべての<img>タグに一致し、もう1 つはそのsrc中の属性に一致します。

私のJavaはさびているので、疑似コードソリューションを提供します:

foreach( imgTag in input.match( /<img .*?>/ig ) ) {
    src = imgTag.match( /\bsrc *= *(['\"])(.*?)\1/i );
    // if you want to get other attributes, you can do that the same way:
    alt = imgTag.match( /\balt *= *(['\"])(.*?)\1/i );
    // even better, you can get all the attributes in one go:
    attrs = imgTag.match( /\b(\w+) *= *(['\"])(.*?)\2/g );
    // attrs is now an array where the first group is the attr name
    // (alt, height, width, src, etc.) and the second group is the
    // attr value
}

適切なタイプの終了引用符に一致する後方参照の使用に注意してください (つまり、これは and に一致src='abc'します。また、量指定子がここでは (単に ではなく)src="abc"遅延していることにも注意してください。これは、過度に消費されるのを防ぐために必要です。*?*

編集:私のJavaは錆びていましたが、例を出すことができました。Javaでの解決策は次のとおりです。

import java.util.regex.*;

public class Regex {

    public static void main( String[] args ) {
        String input = "<img alt=\"altText\" src=\"src\" height=\"50\" width=\"50\"/> <img alt='another image' src=\"foo.jpg\" />";
        Pattern attrPat = Pattern.compile( "\\b(\\w+) *= *(['\"])(.*?)\\2" );
        Matcher imgMatcher = Pattern.compile( "<img .*?>" ).matcher( input );
        while( imgMatcher.find() ) {
            String imgTag = imgMatcher.group();
            System.out.println( imgTag );
            Matcher attrMatcher = attrPat.matcher( imgTag );
            while( attrMatcher.find() ) {
                String attr = attrMatcher.group(1);
                System.out.format( "\tattr: %s, value: %s\n", attrMatcher.group(1), attrMatcher.group(3) );
            }
        }
    }
}
于 2013-10-01T21:40:29.750 に答える