使用正则表达式查找不在注释中的CSS类名称

时间:2018-02-12 19:29:59

标签: css regex class comments

我试图替换CSS文件中的所有类名。我正在使用JavaScript / Node.js.

我目前的解决方案是:/\.[a-z][a-z0-9-_]*/g。 在文件的末尾是一个引用源映射文件的注释:/*# sourceMappingURL=style.css.map */。现在,该URL的文件扩展名也将被替换。

给出以下输入:

.text-center { text-align: center; }
table.simple{background:#fff;}.bg-white{background:#fff;}
/*# sourceMappingURL=style.css.map */
/*
Example comment file.css
*/

结果是:

.a { text-align: center; }
table.a{background:#fff;}.a{background:#fff;}
/*# sourceMappingURL=style.a.a */
/*
Example comment file.a
*/

我想要的是:

.a { text-align: center; }
table.a{background:#fff;}.a{background:#fff;}
/*# sourceMappingURL=style.css.map */
/*
Example comment file.css
*/

我如何更改我的RegEx,以便它只匹配注释之外的类名(//注释与此无关)?

4 个答案:

答案 0 :(得分:2)

试试这个正则表达式:

\.[^{\s]*(?=\s*{)

并将每个匹配项替换为.a

<强> Click for Demo

<强>解释

  • \. - 匹配.
  • [^{\n]* - 匹配任何既不是空格也不是{
  • 的字符的出现次数
  • (?=\s*{) - 积极前瞻以确保当前位置后跟0 +空格后跟{

现在,如果我们有格式

的注释,上面的正则表达式就会失败
/*# sourceMappingURL=style.css.map {*/

{在评论中css.map之后出现。因此,要处理这种情况,您可以使用以下正则表达式(几乎与之前的正则表达式相似。正则表达式的另一个负面预测)

\.[^{\s]*(?=\s*{)(?!(?:(?!\/\*)[\s\S])*\*\/)

<强> Click for Demo

<强>解释

  • \.[^{\s]*(?=\s*{) - 与之前的正则表达式相似
  • (?!(?:(?!\/\*)[\s\S])*\*\/) - 否定前瞻以确保.classname形式的评论中不存在当前位置(/*...*/后面的位置)
    • (?!.... - 负向前瞻
    • (?:(?!\/\*)[\s\S])* - tempered greedy token可以贪婪地匹配任何字符的0次出现,而不是以序列/*
    • 开头
    • \*\/ - 匹配*/

答案 1 :(得分:1)

这两种方法都适用于不同的情况,例如ids之间的类或选择中的多个类:

.class-a, #id-a, .class-b:hover {}

第一种方法

在第一种方法中,您可以匹配注释部分和CSS类,然后在匹配时替换类名并保留注释:

\/\*[\s\S]*?\*\/|(\.[a-z_-][\w-]*)(?=[^{}]*{)
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 Match comments    Match and capture classes

故障:

\/\*[\s\S]*?\*\/    # Match a comment block
|                   # Or
(                   # Start of capturing group #1
    \.[a-z_-][\w-]* # Match a CSS class name
)                   # End of CG #1
(?=                 # Start of a positive lookahead
    [^{}]*{         # Class should be followed by a `{` (may not be immediately)
)                   # End of lookahead

JS代码:

var str = `.text-center { text-align: center; }
table.simple{background:#fff;}.bg-white{background:#fff;}
/*# sourceMappingURL=style.css.map */
/*
Example comment file.css
*/`

console.log(str.replace(/\/\*[\s\S]*?\*\/|(\.[a-z_-][\w-]*)(?=[^{}]*{[^{}]*})/g,
    function($0, $1) {
        return $1 ? '.a' : $0; // If a class is matched ...
    }
));

第二种方法

如果您在评论中没有想到这样的事件将会存在:

/* style.css {css file} */

您可以在第一种方法中省略匹配的评论:

\.[a-z_-][\w-]*(?=[^{}]*{[^{}]*})
                         ^^^^^^^ 
             Added for a more strict selection

RegEx live demo

JS代码:

var str = `.text-center { text-align: center; }
table.simple{background:#fff;}.bg-white{background:#fff;}
/*# sourceMappingURL=style.css.map */
/*
Example comment file.css
*/`

console.log(str.replace(/\.[a-z_-][\w-]*(?=[^{}]*{[^{}]*})/g, '.a'));

答案 2 :(得分:0)

我已经在 pcre flavor

中使用以下RegEx
/(\/\*)?(?(1)(.*\*\/)|(\.[a-z][a-z0-9-_]*))/g

我正在使用条件语句。每当它检测到评论的开始时,它都不会查找类名,而是查找评论的结尾。但是,这不适用于多行评论。类名是第三个捕获组。因此,要替换类名,只需触摸包含捕获组3的匹配项。

我没注意到我在regex101.com上使用了pcre而不是javascript,最后在我的JS代码中出现了语法错误。我现在正在努力寻找适用于JS的解决方案。

编辑:

我现在把它移植到JS:

/(?=\/\*)|(\.[a-z][a-z0-9-_]*)(?!.*\*\/)/g

我仍然需要找到一种方法让它与多行一起使用。

答案 3 :(得分:-1)

使用以下正则表达式,您应该能够从css文件中提取所有不在评论中的类名。 类名以点(。)

开头很重要

正则表达式:

/^.[a-z][a-z0-9-_].*?[\s]/mg

enter image description here