sed 正则表达式用于修复 CSS 缩小问题



我目前正在处理一个缩小任务作为提交后的钩子。我正在使用当前版本的yui压缩器进行CSS缩小。

当前版本的yui-compressor的坏处: 它破坏了某些需要空格才能正常运行的 CSS3 规则。(计算(10px + 10px))

为了解决这个问题,我写了一个正则表达式,应该替换压缩后每次出现的 calc(...)。

到目前为止,我的解决方案是以下正则表达式:

匹配:/calc((.*?)([/+-*])(.*?))/g

替换:calc(1 2 3)

我使用了两个在线工具来验证我的正则表达式:

https://regex101.com/

https://regexr.com/

它也适用于PHP。但是一旦我使用"sed",每行的最后一个出现次数就会被替换:

压缩 CSS:(替换为正则表达式之前)

.test{width:calc(1px+1px)}.test2{left:calc(4%+140px)}.test3{width:calc(1px+1px)}
.test{width:calc(1px-1px)}.test2{left:calc(4%-140px)}.test3{width:calc(1px-1px)}
.test{width:calc(1px*1px)}.test2{left:calc(4%*140px)}.test3{width:calc(1px*1px)}
.test{width:calc(1px/1px)}.test2{left:calc(4%/140px)}.test3{width:calc(1px/1px)}

正则表达式后的 CSS:(和正确的结果)

.test{width:calc(1px + 1px)}.test2{left:calc(4% + 140px)}.test3{width:calc(1px + 1px)}
.test{width:calc(1px - 1px)}.test2{left:calc(4% - 140px)}.test3{width:calc(1px - 1px)}
.test{width:calc(1px * 1px)}.test2{left:calc(4% * 140px)}.test3{width:calc(1px * 1px)}
.test{width:calc(1px / 1px)}.test2{left:calc(4% / 140px)}.test3{width:calc(1px / 1px)}

Debian 8 中的 sed - (从文件加载相同的规则):

sed -r "s/calc((.*?)([/+-*])(.*?))/calc(1 2 3)/g" style.css

打印以下内容:

.test{width:calc(1px+1px)}.test2{left:calc(4%+140px)}.test3{width:calc(1px + 1px)}
.test{width:calc(1px-1px)}.test2{left:calc(4%-140px)}.test3{width:calc(1px-1px)}
.test{width:calc(1px*1px)}.test2{left:calc(4%*140px)}.test3{width:calc(1px * 1px)}
.test{width:calc(1px/1px)}.test2{left:calc(4%/140px)}.test3{width:calc(1px / 1px)}

它似乎不适用于 sed。有谁知道到底发生了什么?

提前感谢!

您正在尝试使用 PCRE 非贪婪重复.*?,但sed仅支持 POSIX BRE 和 ERE,它们没有定义非贪婪扩展。

相反,您必须修改正则表达式。在您的情况下,您可以将[^-+*/]*用于第一个捕获的组(左操作数)——匹配运算符之前的所有内容,[^)]*匹配第二个操作数——直到右括号的所有内容。这将产生您期望的输出:

sed -E 's/calc(([^-+*/]*)([-+*/])([^)]*))/calc(1 2 3)/g' style.css
#                ^^^^^^^^  ^^^^^^  ^^^^^
#            left operand    op    right operand 
#            all until op          all until )

注意-E等同于-r,但也可以在非GNUsed中使用。此外,您无需在括号内转义运算符。事实上,括号内几乎不需要转义任何东西 - 除了右括号(如果未作为第一个字符提供)和^如果作为第一个字符提供。

当你注意到.*?被视为贪婪.*,重复零次或多次(?)时,你得到的输出很容易解释 - 第一个.*?捕获所有内容,直到行中的最后一个运算符,第二个.*?将捕获最后一个操作数,因此仅"扩展"每行中的最后一个calc表达式。

最新更新