如何使用awk macOS(POSIX)在单行中格式化CSS



输入文件是缩小的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 '{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程序

我有一个适用于您的程序,但必须重新解释规则,如果我的规则是错误的,它可能不适用于您希望处理的每一个案件(如果是,请道歉)。

解释

我的目标是:

  1. 如果一行上第一个打开的{样式块在另一个块打开之前被关闭(}),则新行会在该块关闭后立即开始。

  2. @media规则只能位于一行的开头。

  3. 对于包含其他块的块,因此以}}结尾,换行符总是跟在双闭包后面。

方法概述

该过程使用两个awk过程,第一个从数据文件接收输入,第二个从第一个的输出获取输入。在给出使用管道连接的组合程序之前,我将首先单独解释它们的工作原理。

第一个awk步骤

第一个awk步骤修改输入行,以考虑上面的规则3(}}只能在行的末尾)。这是通过使用FS="}}"awk字段分隔符设置为双闭包来实现的。循环用于打印每个字段(后面跟着}},否则会丢失),使awk使用其默认输出记录分隔符ORS(新行)将字段分隔到各自的行上:

awk 'BEGIN{FS="}}"} {for(i=1;i<NF;i++) print $i"}}"; print $NF}' mini.css

第一个awk步骤会产生以下输出(不需要保存到文件中,因为它稍后会"管道化"到第二个awk过程中):

.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}

请注意,在这个阶段,除了最后一行外,所有行都以}}}}终止,在一行内部永远不存在规则3通过该步骤得到满足。

第二个awk步骤第三个awk步骤通过管道接收来自第一个步骤的上述输出。它执行两个功能:

首先,该过程检查一条线上的第一个打开块{是否在打开另一个之前关闭}。如果它被关闭,则会为该行的其余部分引入一行新行,除非在特定情况下,第二个}出现在仅打开一个{之后,如@media only screen and (min-width: 1441px){.classX(color:blue}}之上输出的第三行中(这可能是原始文件中的打字错误,其中.classX之后的(本应为{)。如果这是一个拼写错误并得到纠正,那么检查将变得无关紧要,但无害。(有关更正,请参阅结束语)。

通过将输入行划分为由{分隔的字段来进行检查。字段分隔符设置在BEGIN块中。同时,输出字段分隔符设置为相同的大括号,以在打印字段时替换{

BEGIN{FS="{"; OFS="{"}

现在,如果在字段2中出现},则它在打开另一个块之前关闭第一个块,因此在使用替换在关闭之后插入换行符:

$2~"}"{if (NF>2) sub("}","}n",$2);}

请注意条件pattern$2~"}"的使用,它仅在字段2中出现}时应用操作。这满足了上述规则1

其次,该过程检查第一个字段之后的每个字段,看看它是否包含媒体查询,如果存在@,则进行替换,在其之前插入换行符,以便媒体查询开始新行(规则2)。

第二CCD_ 36过程中的最后一个CCD_。

下面是第二个完整的过程(注意,如果没有第一个过程的输出通过管道传输或作为文件提供,这将无法运行:

awk 'BEGIN{FS="{"; OFS="{"} $2~"}"{if (NF>2) sub("}","}n",$2);} {for(i=2;i<=NF;++i) sub("@","n@",$i)} {print}' 

整个过程

以下是通过管道组合的两个程序:

awk 'BEGIN{FS="}}"} {for(i=1;i<NF;i++) print $i"}}"; print $NF}' mini.css | awk 'BEGIN{FS="{"; OFS="{"} $2~"}"{if (NF>2) sub("}","}n",$2);} {for(i=2;i<=NF;++i) sub("@","n@",$i)} {print}'

请注意,在本例中名为mini.css的数据文件是第一个awk过程的参数。第一个过程的输出通过管道输送到第二个过程。

测试结果

(使用GNU Awk 5.2.0在Mac终端上测试)

这是问题中单行示例数据的输出,保存为mini.css,并在整个过程下使用上面的组合awk脚本进行处理:

.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}

关于可能的打字错误的说明如果这部分原始数据:

@media only screen and (min-width: 1441px){.classX(color:blue}}

旨在:

@media only screen and (min-width: 1441px){.classX{color:blue}}

则第二过程中的CCD_ 41变为冗余。工作加入程序将是:

awk 'BEGIN{FS="}}"} {for(i=1;i<NF;i++) print $i"}}"; print $NF}' mini.css | awk 'BEGIN{FS="{"; OFS="{"} $2~"}"{sub("}","}n",$2);} {for(i=2;i<=NF;++i) sub("@","n@",$i)} {print}'

使用GNUsed

$ sed -E 's/[^}]*}}?([^}]*}})?/&n/g' input_file
.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}}

相关内容

  • 没有找到相关文章

最新更新