我想要一个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
答案 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)
答案 3 :(得分:2)
答案 4 :(得分:2)
您无法使用正则表达式选择css 选择器,但您可以使用正则表达式选择css 规则,这样您就可以完成工作相反的方式:
格式化css文件,以便在同一行中没有选择器和规则。 您的代码应如下所示:
p {
保证金:0 0 10px;
}
.lead {
边距:20像素;
字体大小:21px;
字体重量:200;
行高:30像素;
}
选择所有规则(正则表达式:(^(。)*;)
p {
保证金:0 0 10px;
}
.lead {
的边距:20像素;
字体大小:21px;
字体重量:200;
行高:30像素; 强>
}
为规则添加一些前缀(例如####)
p {
#### margin:0 0 10px;
}
.lead {
的 ####边距:20像素;
####字体大小:21px;
####字体重量:200;
####行高:30像素; 强>
}
选择所有不以####开头的行,而不是返回行,而不是}}(正则表达式:^ [^ #### \ n}])
<强> p {强>
#### margin:0 0 10px;
}
的 .lead {强>
####边距:20像素;
####字体大小:21px;
####字体重量:200;
####行高:30像素;
}
添加你的css前缀
.my_class_prefix p {
#### margin:0 0 10px;
}
.my_class_prefix .lead {
####边距:20像素;
####字体大小:21px;
####字体重量:200;
####行高:30像素;
}
删除添加的前缀####
.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
我确定它缺少一些边缘情况,但似乎对我有用。
答案 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());
}