我正在使用 pyparsing 来解析 sass 文件。我需要将 sass 文件转换为特定格式才能使用它们,保留空格非常重要。
import pyparsing as pp
pp.ParserElement.set_default_whitespace_chars('')
def parse(input_str):
nested_exp = pp.nestedExpr('{','}').parseString("{"+input_str+"}").asList()
return nested_exp
input_str = """selector
{
a:b;
c:d;
selector
{
a:b;
c:d;
}
y:z;
}"""
my_output = parse(input_str)
Expected Output:
[['selector\n',['\n a:b;\n c:d;\n selector\n',['\n a:b;\n c:d;\n'],'\n y:z;\n']]]
My output:
[['selector', ['a:b;\n c:d;\n selector', ['a:b;\n c:d;'], 'y:z;']]]
注意“a:b;”之前应该有 2 个空格和“y:z;”。即使我使用了 set_default_whitespace_chars(''),为什么 pyparsing 会删除它们?一些空格被删除,而另一些则没有。
nested_expr
对所需的结果内容做出了许多假设,最值得注意的是,构成表达式“内容”的项目将是空格分隔的值。所以由此而来:
pp.nestedExpr().parse_string("(1 2 3( 4 5) 'xyz()')").as_list()
我们得到这个:
[['1', '2', '3', ['4', '5'], "'xyz()'"]]
您可以传递一些参数来自定义它,例如定义
ignore_expr
(默认为 quoted_string
expr,以便引号内的括号不会意外地被解析为嵌套分隔符)。您还可以尝试更具体地定义应该位于嵌套表达式内的 content
,例如获取嵌套整数列表的示例:
nested_ints = pp.nested_expr(content=pp.DelimitedList(pp.common.integer))
result = nested_ints.parse_string("(1,2(3,4,5)(6)7)")
print(result.as_list())
[[1, 2, [3, 4, 5], [6], 7]]
感谢您将其提取为易于重现的示例。不幸的是,你如何解决这个问题取决于你试图用这个嵌套列表做什么。
如果您只想检测嵌套列表并保持其完整,您可以将表达式包装在
original_text_for
帮助器中,如下所示:
nested_exp = pp.original_text_for(pp.nestedExpr('{','}')).parseString("{"+input_str+"}").asList()
这只是将原始文本作为字符串返回:
['{selector\n{\n a:b;\n c:d;\n selector\n {\n a:b;\n c:d;\n }\n y:z;\n}}']
您可以看到这保留了所有内部空白,尽管这与您发布的预期列表不匹配。
不幸的是,
nested_expr
的当前实现会进行一些内部空白剥离,即使您已将默认空白字符设置为''
。我将考虑在下一个版本中使其更加了解默认值。现在,您可能需要滚动自己的 nested_expr
来保留空白,如下所示:
opener = "{"
closer = "}"
ignoreExpr = pp.quoted_string().leave_whitespace()
content = pp.Combine(
pp.OneOrMore(
~ignoreExpr
+ pp.CharsNotIn(
opener + closer + pp.ParserElement.DEFAULT_WHITE_CHARS,
exact=1,
)
)
)
nested_expr = pp.Forward()
nested_expr <<= pp.Group(pp.Suppress(opener) + (nested_expr | content)[...] + pp.Suppress(closer))
def parse(input_str):
nested_exp = nested_expr.parseString("{"+input_str+"}").asList()
return nested_exp