如何在macOS(POSIX)环境下用awk格式化单行压缩CSS
解决压缩CSS按规则换行的awk实现问题
压缩后的原始CSS
.class{margin:0px}.class1,.class2{margin 0px}@media{.class{color:blue}.class1,.class2{color:red}}@media{.classA.classB,.classC{margin:0px}}@media{.classD,.classE{color:blue}.class1,.class2{color:red}}@media only screen and (min-width: 1441px){.classX{color:blue}}@media only screen and (min-width: 1441px){.class{color:blue}.class1,.class2{color:red}}@media only screen and (min-width: 1441px){.classA.classB,.classC{margin:0px}}@media only screen and (inverted-colors){.classD,.classE{color:blue}.class1,.class2{color:red}.classV{color:red}.classR{color:red}.classU{color:red}.classS{color:red}.classT{color:red}}.classNew{margin: 10px}
期望的格式化结果
.class{margin:0px} .class1,.class2{margin 0px} @media{.class{color:blue}.class1,.class2{color:red}} @media{.classA.classB,.classC{margin:0px}} @media{.classD,.classE{color:blue}.class1,.class2{color:red}} @media only screen and (min-width: 1441px){.classX{color:blue}} @media only screen and (min-width: 1441px){.class{color:blue}.class1,.class2{color:red}} @media only screen and (min-width: 1441px){.classA.classB,.classC{margin:0px}} @media only screen and (inverted-colors){.classD,.classE{color:blue}.class1,.class2{color:red}.classV{color:red}.classR{color:red}.classU{color:red}.classS{color:red}.classT{color:red}} .classNew{margin: 10px}
错误的尝试及结果
使用以下awk命令:
awk '{gsub(/\t?}/, "}\n"); print}'
得到的错误结果:
.class{margin:0px} .class1,.class2{margin 0px} @media{.class{color:blue} .class1,.class2{color:red} } @media{.classA.classB,.classC{margin:0px} } @media{.classD,.classE{color:blue} .class1,.class2{color:red} } @media only screen and (min-width: 1441px){.classX{color:blue} } @media only screen and (min-width: 1441px){.class{color:blue} .class1,.class2{color:red} } @media only screen and (min-width: 1441px){.classA.classB,.classC{margin:0px} } @media only screen and (inverted-colors){.classD,.classE{color:blue} .class1,.class2{color:red} .classV{color:red} .classR{color:red} .classU{color:red} .classS{color:red} .classT{color:red} } .classNew{margin: 10px}
正确的awk实现
核心思路是跟踪大括号的嵌套层级,仅在顶级规则的闭合}后添加换行,内部嵌套的}不处理。对应的awk脚本如下:
awk '{ len = length($0) depth = 0 for (i=1; i<=len; i++) { c = substr($0, i, 1) if (c == "{") { depth++ printf "%s", c } else if (c == "}") { depth-- printf "%s", c # 仅当回到顶级层级时添加换行 if (depth == 0) { printf "\n" } } else { printf "%s", c } } }'
工作原理
- 初始化
depth变量记录括号嵌套深度,初始值为0。 - 逐个遍历输入字符串的每个字符:
- 遇到
{时,深度加1并直接输出该字符; - 遇到
}时,深度减1后输出该字符,若此时深度回到0,说明是顶级规则(如单个类规则、完整的@media块)的结束,追加换行; - 其他字符直接输出。
- 遇到
这样就能保证所有顶级规则(包括整个@media块)单独占一行,内部嵌套的规则保持紧凑不拆分,完全符合期望的格式化效果。
内容的提问来源于stack exchange,提问作者Sharad Shrestha
相关产品推荐
相关产品推荐

