如何将代码块拆分为列表?

5

我想要用Python 3.5将CSS文件的内容分割成代码块,并将每个代码块推入一个列表中。

因此,考虑到以下CSS:

h1 {color: #333, background-color: transparent}
h2 {
  font-weight:300
}
h3
{
  font-weight: 200
}

我们可以清楚地看到它具有多种不同的缩进样式和/或类型,这意味着CSS必须进行整理才能获得以下效果:
h1 {
  color: #333,background-color: transparent;
}

h2 {
  font-weight: 300;
}

h3 {
  font-weight: 200;
}

我该如何使用Python读取经过整理的CSS字符串,并将其中每个代码块推入Python列表中,像这样:
styles = [
  "h1 {\n  color: #333,background-color: transparent;\n}",
  "h2 {\n  font-weight: 300;\n}",
  "h3 {\n  font-weight: 200;\n}"
]

我想指出的是,RegExp不是我的强项,我不太确定要使用哪个RegEx,但我认为可以使用RegExp和[].split(...);一起实现这个目标。
甚至可以使用RegExp来消除在拆分代码块之前整理样式表的需要。
注意:我已经查看了此问题,但遗憾的是那也没有帮助。

@pvg 不好意思,那个方法并没有解决我的问题。 - user5870134
@Mango 不需要自己实现解析器,你可以使用一个小型库。我在下面的答案中概述了它。 - oxalorg
1
@Mango,实际上确实可以,你想要解决问题的方式类似于这个臭名昭著的SO答案https://dev59.com/X3I-5IYBdhLWcg3wq6do#1732454 不要这样做,使用解析器,有一些小而高效的解析器可以简单而正确地完成此任务。 - pvg
2个回答

3

这个实现是使用 tinycss 完成的,它是一个简单的纯 Python CSS 解析器

这适用于未格式化(untidied)的 CSS。只要它是合法的。

import tinycss
from collections import defaultdict

parser = tinycss.make_parser('page3')
# use parse_stylesheet_files to read from a file.
stylesheet = parser.parse_stylesheet("""h1 {color: #333; background-color: transparent}
        h2 {
              font-weight:300
        }
        h3
        {
              font-weight: 200
        }
        h1{
        padding: 0px;}
        """)

# Initialize to empty list if key does not exists
# This allows to group multiple blocks with same selectors
temp = defaultdict(list)

for rule in stylesheet.rules:
    for dec in rule.declarations:
       temp[rule.selector.as_css()].append((dec.name, dec.value.as_css()))

print(temp)

输出:

defaultdict(<class 'list'>,
            {'h1': [('color', '#333'),
                    ('background-color', 'transparent'),
                    ('padding', '0px')],
             'h2': [('font-weight', '300')],
             'h3': [('font-weight', '200')]})

看看不同的h1块是如何组合成一个单一的列表的。我对CSS的细节不是非常了解,但很容易防止这种情况发生。

这种方法更加灵活,因为它覆盖了所有边缘情况,适用于选择器、CSS2和CSS3,而不像正则表达式的解决方案那样有局限性。

请注意:我将所有内容都放入了一个字典中,但您也可以轻松地将其作为列表推入。如果您理解我的做法,就应该相对容易。如果您需要纯列表,请告诉我。


正则表达式无法涵盖哪些情况?假设CSS始终格式正确,它应该始终有效。https://repl.it/C5ws/7 - Jacob G
@JacobGray 假设它已经正确格式化。如果没有,您仍然需要一个解析器,因此最好有一种方法可以在不需要整理CSS的情况下解决它。 - oxalorg
2
如果存在一个额外的空格,你的解决方案就会完全崩溃,而且还会默默无闻。注释、注释内的括号、完整的代码块、制表符等都是边缘情况,使用正则表达式处理这样的问题绝对是个坏主意。 - oxalorg
这段代码如果使用defaultdict可以让它更短更清晰,避免了if判断。另外,字符串前面的b前缀真的有必要吗? - pvg
1
@MiteshNinja,感谢您的回答,它非常出色。 - user5870134
显示剩余4条评论

1
你可以通过简单的文件读取和替换来实现这一点:
styles = []
with open('file.css') as file:
    style = []
    for line in file.readlines():
        # If line is empty
        if not line.strip():
            # If a block is non-empty
            if style:
                styles.append("".join(style))
                style = []
        else:
            # Add to the current block
            style.append(line)
    styles.append("".join(style))

输出:

>>> for s in styles: s
h1 {\n  color: #333,background-color: transparent;\n}\n
h2 {\n  font-weight: 300;\n}\n
h3 {\n  font-weight: 200;\n}\n

即使整个 CSS 样式表中有一行额外的空白行,这段代码也会出现严重错误。 - oxalorg
@MiteshNinja 通过“糟糕地破坏”,我想你是指styles中会有空行(如果你指的是其他内容,请澄清)。感谢您指出这一点。已经修复了。 - th3an0maly
我觉得你可能理解错了。如果代码中除了在两个代码块之间的换行符外,任何地方都有多余的空白行,那么你的代码将会出现严重的错误。如果在一个代码块内部有多余的空行,它会认为该代码块已经结束,并将其推入 styles 中。请再次检查你的代码。 - oxalorg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接