c# - 处理多个正则表达式组

标签 c# regex

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

我需要做的是:

  1. 循环遍历我的匹配项,获取 filename 组捕获
  2. 检查是否存在相应的media
  3. 如果是这样,将整个加载的 css 包装在带有捕获参数的媒体查询中
  4. 如果没有,只添加文件名捕获内容。

例如

@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;
    }

最佳答案

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

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

关于c# - 处理多个正则表达式组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11637678/

相关文章:

javascript - 使用javascript在mvc路由的一部分中有效增加数字

java - 通过正则表达式从字符串中删除前导换行符?

javascript - 将脏话过滤器添加到简单的 Socket.IO 应用程序

c# - 注入(inject)属性不适用于字段

c# - 如何删除Point结构的值?

c# - Unicode 到 Mazovia 编码冗余字符

php - 如何在 PHP 中替换字符串中的单个单词?

c# - 如何将图片合并到 WriteableBitmap 中?

c# - 覆盖子类中的字段或属性

regex - sed 脚本扩展正则表达式