简体   繁体   English

CSS 选择器的正则表达式是什么

[英]What is the regex of a CSS selector

I'd like to parse a CSS file and add another CSS selector before every CSS selector.我想解析一个 CSS 文件并在每个 CSS 选择器之前添加另一个 CSS 选择器。

From:从:

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

I'd like:我想要:

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

But my CSS file is really complex (in fact it is the bootstrap CSS file), so the regex should match all CSS selectors.但是我的 CSS 文件非常复杂(实际上它是引导 CSS 文件),因此正则表达式应该匹配所有 CSS 选择器。

For now, I have this regex:现在,我有这个正则表达式:

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

And you can see the result here http://regexr.com?328ps , but as you can see, there are a lot of matches that shouldn't match.你可以在这里看到结果http://regexr.com?328ps ,但正如你所看到的,有很多匹配不应该匹配。

For example:例如:

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

matches positive but it shouldn't匹配正数,但不应该

Does someone have a solution?有人有解决方案吗?

There isn't one.没有一个。 CSS selectors are not an example of a " Regular Language " and so cannot be parsed by a Regular Expression. CSS 选择器不是“正则语言”的一个例子,因此不能被正则表达式解析。 You will need to build your own parser based on the CSS grammar specification: http://www.w3.org/TR/css3-syntax/#detailed-grammar您需要根据 CSS 语法规范构建自己的解析器: http : //www.w3.org/TR/css3-syntax/#detailed-grammar

CSS is described as an LL(1) grammar, so you're probably better off using a tool like Yacc to generate your parser for you. CSS 被描述为 LL(1) 语法,因此您最好使用 Yacc 之类的工具为您生成解析器。

So I've finally found a REGEX that works for my requirements所以我终于找到了适合我的要求的 REGEX

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

The key point was to add a Positive lookahead to avoid bad matches关键点是添加一个Positive Lookahead以避免错误匹配

(?=[^}]*{)

You can see the result here: http://regexr.com?328s7你可以在这里看到结果: http : //regexr.com?328s7

The only precaution that I can recommend is to remove every block comment:我可以推荐的唯一预防措施是删除每个块注释:

So finally I've found a way better way to do it.所以最后我找到了一种更好的方法来做到这一点。

I use a LESS editor (eg: http://lesstester.com/ )我使用 LESS 编辑器(例如: http : //lesstester.com/

and simply nest my whole css file: .mySelector{ your css here }并简单地嵌套我的整个 css 文件: .mySelector{ your css here }

It's true that you can not select css selectors using regex, but you can select css rules using regex, so you can make the job done in the inverse way:确实,您不能使用正则表达式选择 css选择器,但是您可以使用正则表达式选择 css规则,因此您可以以相反的方式完成工作:

  1. format css file in order to no have selectors and rules in the same line.格式化 css 文件,以便在同一行中没有选择器和规则。 your code should look like this:您的代码应如下所示:

    p{ p{
    margin:0 0 10px;边距:0 0 10px;
    } }
    .lead{ 。带领{
    margin-bottom:20px;底边距:20px;
    font-size:21px;字体大小:21px;
    font-weight:200;字体粗细:200;
    line-height:30px;行高:30px;
    } }

  2. select all rules (regex : (^(.)*;)选择所有规则(正则表达式 : (^(.)*;)

    p{ p{
    margin:0 0 10px;边距:0 0 10px;
    } }
    .lead{ 。带领{
    margin-bottom:20px;底边距:20px;
    font-size:21px;字体大小:21px;
    font-weight:200;字体粗细:200;
    line-height:30px;行高:30px;
    } }

  3. add some prefix to rules (example ####)为规则添加一些前缀(例如####)

    p{ p{
    ####margin:0 0 10px; ####margin:0 0 10px;
    } }
    .lead{ 。带领{
    ####margin-bottom:20px; ####margin-bottom:20px;
    ####font-size:21px; ####字体大小:21px;
    ####font-weight:200; ####字体权重:200;
    ####line-height:30px; ####行高:30px;
    } }

  4. select all lines not beginning with ####,not a return to line, and not a } (regex : ^[^#### \\n }])选择所有不以 #### 开头的行,而不是返回行,而不是 } (正则表达式:^[^#### \\n }])

    p{ p{
    ####margin:0 0 10px; ####margin:0 0 10px;
    } }
    .lead{ 。带领{
    ####margin-bottom:20px; ####margin-bottom:20px;
    ####font-size:21px; ####字体大小:21px;
    ####font-weight:200; ####字体权重:200;
    ####line-height:30px; ####行高:30px;
    } }

  5. add your css prefix添加你的css前缀

    .my_class_prefix p{ .my_class_prefix p{
    ####margin:0 0 10px; ####margin:0 0 10px;
    } }
    .my_class_prefix .lead{ .my_class_prefix .lead{
    ####margin-bottom:20px; ####margin-bottom:20px;
    ####font-size:21px; ####字体大小:21px;
    ####font-weight:200; ####字体权重:200;
    ####line-height:30px; ####行高:30px;
    } }

  6. delete the added prefix ####删除添加的前缀####

    .my_class_prefix p{ .my_class_prefix p{
    margin:0 0 10px;边距:0 0 10px;
    } }
    .my_class_prefix .lead{ .my_class_prefix .lead{
    margin-bottom:20px;底边距:20px;
    font-size:21px;字体大小:21px;
    font-weight:200;字体粗细:200;
    line-height:30px;行高:30px;
    } }

A simple and readable regex is below:一个简单易读的正则表达式如下:

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

you can test it on css code in this tool `您可以在此工具中的css 代码上对其进行测试`

Faced a similar problem and used the following to extract only CSS selectors and directives without comments and media queries:面临类似的问题,并使用以下内容仅提取 CSS 选择器和指令,而没有评论和媒体查询:

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

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

I'm sure it's missing some edge-cases but seems to be working for me.我确定它缺少一些边缘情况,但似乎对我有用。

See this question: Ruby RegExp - Match all CSS selectors and directives请参阅此问题: Ruby RegExp - 匹配所有 CSS 选择器和指令

这就是我想出的:

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

Here's the solution I used for a similar problem.这是我用于类似问题的解决方案。 I wanted to remove all css rules that started with @ .我想删除所有以@开头的 css 规则。 For this I used the following regex:为此,我使用了以下正则表达式:

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

It makes the assumption that the rule ends on a new line.它假设规则以新行结束。 That way it can sort of handle nested css rules.这样它就可以处理嵌套的 css 规则。

While it isn't possible to write a single regular expression that matches any valid CSS selector, you can combine a couple regular expressions and a bit of logic to accomplish your goal.虽然无法编写与任何有效 CSS 选择器匹配的单个正则表达式,但您可以组合几个正则表达式和一些逻辑来实现您的目标。

The following uses Node's fs module to read the CSS, but you could get the raw CSS string however you want.下面使用 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(',');

});

Interesting discussion - not pure reg exp but a really short JS function:有趣的讨论 - 不是纯粹的 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());
}

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

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