繁体   English   中英

具有重叠匹配项的多行正则表达式

[英]Multi-line regex with overlapping matches

我正在使用一种工具来分析文件的CSS样式声明。 它使用了一个非常复杂的正则表达式,除了预期的性能问题和一些暂时不会影响我的小错误外,它正在做我想做的所有事情,除了一件事情。

我可以匹配元素名称,类,子类,伪类等的所有组合。但是,当一行包含多个声明时,我只能使其匹配一次。 举例来说,这是目前让我绊倒的事情:

td.class1, td.class2, td.class3
{
    background-color: #FAFAFA;
    height: 10px;
}

我可以编写一个满足所有三个声明都满足的表达式,但是由于我也在此之后捕获信息(方括号内的实际样式信息),因此我觉得整个文本块都应考虑在内,因此引擎将移至刚处理完的整个程序段之后的下一个字符。

有没有一种方法可以做到这一点,即每个类将是一个单独的匹配项,并且所有类都将包含随后的样式信息? 我知道我可以修改我的正则表达式以匹配整行,然后在获得匹配项后将其解析为逗号,但是我想尽可能将所有逻辑保留在表达式本身内。

如果与答案绝对相关,我可以发布用于生成它的表达式和/或注释的代码,但是表达式很大/很丑陋(因为所有非平凡的正则表达式都是这样),并且代码有点长。

您需要CSS解析器,而不是正则表达式。 您可能应该阅读C#是否有CSS解析器

这是一个与示例数据一起使用的正则表达式:

@"([^,{}\s]+(?:\s+[^,{}\s]+)*)(?=[^{}]*(\{[^{}]+\}))"

第一部分匹配并捕获组#1中的一个选择器(td.class1),然后超前跳过所有剩余的选择器并捕获组#2中的关联样式规则。 下次匹配尝试从上一次前瞻开始的地方开始,因此它匹配下一个选择器(td.class2),并且前瞻再次捕获相同的规则块。

这不会处理@-规则或注释,但在您提供的示例数据上可以正常工作。 我什至在一些真实的样式表上进行了检查,效果非常好。

根据正则表达式引擎的细微差别,您可以通过将捕获对象嵌入到前行中来实现此目的,例如:

\.(\w+)(?=.*?{([^}]*)})

我希望弄清楚比赛组的含义是一种练习。

对于正则表达式来说,这不是一个好问题。

另一方面,您肯定只需要几次传递就可以编写基本的CSS解析器。

毕竟,CSS语法只是[一些东西],[大括号],[其他东西],[大括号]。

您找到了这两个部分,您将第一个拆分为逗号,将第二个拆分为分号,您已经完成了很多工作。

我需要对AmbroseChapel所说的内容采取类似的看法,而我在AS3中也需要它,因此我分享了它,以防它对其他人有所帮助。 我试图做到周全,评论会引导您完成整个过程。 我已经在一些流行的CSS样板板上测试了它,并且效果很好。 :)(这仅用于列出选择器名称,而不用于属性解析。)

    public function getSelectors( targetCSS:String, includeElements:Boolean = true ):ArrayCollection
    {

        var newSelectorCollection:ArrayCollection = new ArrayCollection();

        if( targetCSS == null || targetCSS == "" ) return newSelectorCollection;

        var newSelectors:Array = new Array();

        var elements:Array = new Array();
        var ids:Array = new Array();
        var classes:Array = new Array();

        // Remove comments
        var cssString:String = "";
        var commentParts:Array = targetCSS.split( "/*" );

        for( var c:int = 0; c < commentParts.length; c++ ){

            var comPart:String = commentParts[ c ] as String;

            var comTestArray:Array = comPart.split( "*/" );

            if( comTestArray.length > 1 ){

                comTestArray.shift();
                comPart = comTestArray.join( "" );

            }

            cssString += comPart;

        }

        // Remove \n
        cssString = cssString.split( "\n" ).join( "" );
        // Remove \t
        cssString = cssString.split( "\t" ).join( "" );
        // Split at }
        var cssParts:Array = cssString.split( "}" );

        for( var i:int = 0; i < cssParts.length; i++ ){

            var cssPrt:String = cssParts[ i ] as String;

            // Detect nesting such as media queries by finding more than one {
            var nestingTestArray:Array = cssPrt.split( "{" );

            // If there is nesting split at { then drop index 0 and re-join with {
            if( nestingTestArray.length > 2 ){

                nestingTestArray.shift();
                cssPrt = nestingTestArray.join( "{" );

            }

            // Split at each item at {
            var cssPrtArray:Array = cssPrt.split( "{" );

            // Disregard anything after {
            cssPrt = cssPrtArray[ 0 ] as String;

            // Split at ,
            var selectorList:Array = cssPrt.split( "," );

            for( var j:int = 0; j < selectorList.length; j++ ){

                var sel:String = selectorList[ j ] as String;

                // Split at : and only keep index 0
                var pseudoParts:Array = sel.split( ":" );

                sel = pseudoParts[ 0 ] as String;

                // Split at [ and only keep index 0
                var attrQuryParts:Array = sel.split( "[" );

                sel = attrQuryParts[ 0 ] as String;

                // Split at spaces
                var selectorNames:Array = sel.split( " " );

                for( var k:int = 0; k < selectorNames.length; k++ ){

                    var selName:String = selectorNames[ k ] as String;

                    if( selName == null || selName == "" ){

                        continue;

                    }

                    // Check for direct class applications such as p.class-name
                    var selDotIndex:int = selName.indexOf( ".", 1 );
                    if( selDotIndex != -1 ){

                        // Add the extra classes
                        var dotParts:Array = selName.split( "." );

                        for( var d:int = 0; d < dotParts.length; d++ ){

                            var dotPrt:String = dotParts[ d ] as String;

                            if( d > 0 ){

                                dotPrt = "." + dotPrt;

                                if( d == 1 && selName.indexOf( "." ) === 0 ){

                                    selName = dotPrt;

                                }else{

                                    selectorNames.push( dotPrt );

                                }

                            }else{

                                if( dotPrt != "" ){

                                    selName = dotPrt;

                                }

                            }

                        }

                    }

                    // Only add unique items
                    if( newSelectors.indexOf( selName ) == -1 ){

                        // Avoid @ prefix && avoid *
                        if( selName.charAt( 0 ) != "@" && selName != "*" ){

                            newSelectors.push( selName );

                            switch( selName.charAt( 0 ) ){

                                case ".":
                                    classes.push( selName );
                                    break;

                                case "#":
                                    ids.push( selName );
                                    break;

                                default:
                                    elements.push( selName );
                                    break;

                            }

                        }

                    }

                }

            }

        }

        if( includeElements ){

            newSelectorCollection.source = elements.sort().concat( ids.sort().concat( classes.sort() ) );

        }else{

            newSelectorCollection.source = ids.sort().concat( classes.sort() );

        }

        return newSelectorCollection;

    }

暂无
暂无

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

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