处理多个正则表达式组

时间:2012-07-24 19:08:26

标签: c# regex

我正在使用以下代码递归解析css @import语句以在minifer中加载嵌套的css文件。虽然这与标准@import语句完美匹配,但它会错误地将@import语句添加到媒体查询中,而不会围绕它们创建条件。

我需要做的是:

  1. 通过我的比赛循环抓取filename群组抓取
  2. 检查是否存在相应的media
  3. 如果是,请使用捕获的参数
  4. 将整个加载的css包装在媒体查询中
  5. 如果没有,只需添加文件名捕获内容。
  6. e.g

    @import url(style.css) screen and (min-width: 768px);
    

    变为

    @media screen and (min-width: 767px) {
        /* contents of style.css */
    }
    

    我用来捕获语句的正则表达式是这样的:

    (?:@import\surl\()(?<filename>[^.]+\.css)(?:\)((?<media>[^;]+);|;))
    

    这是正确捕捉。我对Regex课程的了解不够充分。

    有人比我想出来更聪明吗?

    我的原始代码。

        /// <summary>
        /// Parses the string for css imports and adds them to the 
        /// file dependency list.
        /// </summary>
        /// <param name="css">
        /// The css to parse for import statements.
        /// </param>
        /// <param name="minify">
        /// Whether or not the local script should be minified.
        /// </param>
        /// <returns>The css file parsed for imports.</returns>
        private string ParseImportsAndCache(string css, bool minify)
        {
            // Check for imports and parse if necessary.
            if (!css.Contains("@import", StringComparison.OrdinalIgnoreCase))
            {
                return css;
            }
    
            // Recursivly parse the css for imports.
            foreach (Match match in ImportsRegex.Matches(css))
            {
                // Recursivly parse the css for imports.
                GroupCollection groups = match.Groups;
    
                // Check and add the @import params to the cache dependancy list.
                foreach (var groupName in groups["filename"].Captures)
                {
                    // Get the match
                    List<string> files = new List<string>();
                    Array.ForEach(
                        CSSPaths,
                        cssPath => Array.ForEach(
                            Directory.GetFiles(
                                HttpContext.Current.Server.MapPath(cssPath),
                                groupName.ToString(),
                                SearchOption.AllDirectories),
                            files.Add));
    
                    string file = files.FirstOrDefault();
                    string thisCSS = string.Empty;
    
                    // Read the file.
                    if (file != null)
                    {
                        using (StreamReader reader = new StreamReader(file))
                        {
                            // Recursiveley parse the css.
                            thisCSS = this.ParseImportsAndCache(reader.ReadToEnd(),
                                                                minify);
                        }
                    }
    
                    // Replace the regex match with the full qualified css.
                    css = css.Replace(match.Value, thisCSS);
    
                    if (minify)
                    {
                        this.cacheDependencies
                            .Add(new CacheDependency(files.FirstOrDefault()));
                    }
                }
            }
    
            return css;
        }
    

1 个答案:

答案 0 :(得分:0)

根据评论中的建议,这是最终的工作代码。

/// <summary>
/// Parses the string for css imports and adds them to the file dependency 
/// list.
/// </summary>
/// <param name="css">
/// The css to parse for import statements.
/// </param>
/// <param name="minify">Whether or not the local script should be minified.
////</param>
/// <returns>The css file parsed for imports.</returns>
private string ParseImportsAndCache(string css, bool minify)
{
    // Check for imports and parse if necessary.
    if (!css.Contains("@import", StringComparison.OrdinalIgnoreCase))
    {
        return css;
    }

    // Recursivly parse the css for imports.
    foreach (Match match in ImportsRegex.Matches(css))
    {
        // Recursivly parse the css for imports.
        GroupCollection groups = match.Groups;
        Capture fileName = groups["filename"].Captures[0];
        CaptureCollection mediaQueries = groups["media"].Captures;
        Capture mediaQuery = null;

        if (mediaQueries.Count > 0)
        {
            mediaQuery = mediaQueries[0];
        }

        // Check and add the @import params to the cache dependancy list.
        // Get the match
        List<string> files = CSSPaths
            .SelectMany(cssPath => Directory.GetFiles(
                HttpContext.Current.Server.MapPath(cssPath),
                Path.GetFileName(fileName.ToString()),
                SearchOption.AllDirectories))
            .ToList();

        string file = files.FirstOrDefault();
        string thisCSS = string.Empty;

        // Read the file.
        if (file != null)
        {
            using (StreamReader reader = new StreamReader(file))
            {
                thisCSS = mediaQuery != null
                    ? string.Format(CultureInfo.InvariantCulture,
                                "@media {0}{{{1}{2}{1}}}",
                                mediaQuery,
                                Environment.NewLine,
                                this.ParseImportsAndCache(
                                this.PreProcessInput(reader.ReadToEnd(), 
                                file),
                                minify))
                    : this.ParseImportsAndCache(this.PreProcessInput(
                                                reader.ReadToEnd(), 
                                                file), 
                                                minify);
            }
        }

        // Replace the regex match with the full qualified css.
        css = css.Replace(match.Value, thisCSS);

        if (minify)
        {
            this.cacheDependencies.Add(new CacheDependency(
                                           files.FirstOrDefault()));
        }
    }

    return css;
}