什么是CSS选择器的REGEX

时间:2012-09-25 03:33:18

标签: css regex

我想要一个CSS文件并在每个CSS选择器之前添加另一个选择器。

自:

p{margin:0 0 10px;}
.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px;}

我想:

.mySelector p{margin:0 0 10px;}
.mySelector .lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px;}

但我的CSS文件非常复杂(事实上它是bootstrap css文件)所以正则表达式应匹配所有CSS选择器。

现在我有这个正则表达式:

([^\r\n,{};]+)(,|{)

您可以在此处查看结果http://regexr.com?328ps 但是你可以看到有很多不匹配的匹配

例如:

text-shadow:0 -1px 0 rgba(0,

匹配正面,但不应该

有人有解决方案吗?

THX

10 个答案:

答案 0 :(得分:22)

没有一个。 CSS选择器不是“Regular Language”的示例,因此无法通过正则表达式进行解析。您需要根据CSS语法规范构建自己的解析器:http://www.w3.org/TR/css3-syntax/#detailed-grammar

CSS被描述为LL(1)语法,所以你最好使用像Yacc这样的工具为你生成解析器。

答案 1 :(得分:20)

所以我终于找到了符合我要求的REGEX

([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)

关键是要添加正向前瞻以避免不良匹配

(?=[^}]*{)

您可以在此处查看结果:http://regexr.com?328s7

我建议的唯一预防措施是删除每个块评论:

答案 2 :(得分:6)

所以最后我找到了一种更好的方法。

我使用LESS编辑器(例如:http://lesstester.com/

并简单地嵌套我的整个css文件: .mySelector {你的css在这里}

答案 3 :(得分:2)

下面是一个简单易读的正则表达式:

[\#\.\w\-\,\s\n\r\t:]+(?=\s*\{)

你可以在这个tool`

的css代码上测试它

答案 4 :(得分:2)

您无法使用正则表达式选择css 选择器,但您可以使用正则表达式选择css 规则,这样您就可以完成工作相反的方式:

  1. 格式化css文件,以便在同一行中没有选择器和规则。 您的代码应如下所示:

      

    p {
          保证金:0 0 10px;
      }
      .lead {
          边距:20像素;
          字体大小:21px;
          字体重量:200;
          行高:30像素;
      }

  2. 选择所有规则(正则表达式:(^(。)*;)

      

    p {
          保证金:0 0 10px;
      }
      .lead {
          的边距:20像素;
          字体大小:21px;
          字体重量:200;
          行高:30像素;
       }

  3. 为规则添加一些前缀(例如####)

      

    p {
           #### margin:0 0 10px;
      }
      .lead {
          的 ####边距:20像素;
          ####字体大小:21px;
          ####字体重量:200;
          ####行高:30像素;
       }

  4. 选择所有不以####开头的行,而不是返回行,而不是}}(正则表达式:^ [^ #### \ n}])

      

    <强> p {
              #### margin:0 0 10px;
          }
          的 .lead {
              ####边距:20像素;
              ####字体大小:21px;
              ####字体重量:200;
              ####行高:30像素;
           }

  5. 添加你的css前缀

      

    .my_class_prefix p {
              #### margin:0 0 10px;
          }
           .my_class_prefix .lead {
              ####边距:20像素;
              ####字体大小:21px;
              ####字体重量:200;
              ####行高:30像素;
           }

  6. 删除添加的前缀####

      

    .my_class_prefix p {
              保证金:0 0 10px;
          }
           .my_class_prefix .lead {
              边距:20像素;
              字体大小:21px;
              字体重量:200;
              行高:30像素;
           }

答案 5 :(得分:1)

这是我想出的:

(?<=\s)[^ ]*\s*\{[^\}]+\:[^\}]+\}

答案 6 :(得分:0)

这是我用于解决类似问题的解决方案。我想删除以@开头的所有css规则。为此,我使用了以下正则表达式:

@\s*.*\s*\{((?!\n\})[\s\S])+\n\}

假设规则以新行结束。这样它就可以处理嵌套的css规则。

答案 7 :(得分:0)

遇到类似的问题,并使用以下内容仅提取CSS选择器和指令,而没有注释和媒体查询:

/^(?!.*@media)[\t ]*([a-zA-Z#.:*\[][^{\/]*\s*){[\s\S]*?}/

示例:https://regex101.com/r/JmjthP/5

我确定它缺少一些边缘情况,但似乎对我有用。

看到这个问题:Ruby RegExp - Match all CSS selectors and directives

答案 8 :(得分:0)

虽然不可能编写与任何有效的CSS选择器匹配的正则表达式,但您可以结合使用几个正则表达式和一些逻辑来实现您的目标。

以下内容使用Node的fs模块读取CSS,但是您可以根据需要获取原始CSS字符串。

const fs = require('fs'),
    myClassName = 'mySelector',
    mySelector = '.' + myClassName,
    mySelectorRegex = new RegExp(`\\.${myClassName}([ .#[:(]|$)`),
    cssSelectorRegex = /[@.#a-zA-Z][^}]*?(?={)/g;

let css = fs.readFileSync('path/to/file.css').toString();

css = css.replace(cssSelectorRegex, match => {

    // Match is a string of selectors like '.foo' or '.foo, #bar'
    // We need to split it on the comma and handle each selector individually
    return match.split(',').map(selector => {

        selector = selector.trim();

        // Don't alter media queries, imports, or selectors that already contain '.mySelector'
        if (selector.startsWith('@') || selector.match(mySelectorRegex)) {

            return selector;

        }

        // Prepend '.mySelector ' to the selector
        return mySelector + ' ' + selector;

    // Combine the list of selectors back together
    }).join(',');

});

答案 9 :(得分:0)

有趣的讨论 - 不是纯粹的 reg exp,而是一个非常短的 JS 函数:

function cssNester(css, nestWith) {
  let kframes = [];
  css = css.replace(/@(-moz-|-webkit-|-ms-)*keyframes\s(.*?){([0-9%a-zA-Z,\s.]*{(.*?)})*[\s\n]*}/g, x => kframes.push(x) && '__keyframes__');
  css = css.replace(/([^\r\n,{}]+)(,(?=[^}]*{)|\s*{)/g, x => x.trim()[0] === '@' ? x : x.replace(/(\s*)/, '$1' + nestWith + ' '));
  return '/*' + nestWith + '*/\n' + css.replace(/__keyframes__/g, x => kframes.shift());
}