如何将带有换行符的字符串转换为文件中具有YAML折叠样式的字符串?

问题描述 投票:0回答:1

在我所拥有的许多YAML文件中,通常存在以下内容:

query: "SELECT\n  *\nFROM\n  (SELECT\n  'apple' AS fruit,\n  'carrot' AS vegetable);"

但我想将上面的内容转换为如下所示:

query: >
SELECT
  *
FROM (
  SELECT
    "apple" AS fruit,
    "carrot" AS vegetable);

在YAML文件中。

我只是希望YAML更具可读性,我想要一种转换字符串的方法,而不必进入我拥有的每个YAML文件并手动更改它们。我已经尝试将上面的字符串打印到stdout并将该输出重定向到变量,但这对我不起作用。

我尝试过的代码:

from contextlib import redirect_stdout
import io

with io.StringIO() as buf, redirect_stdout(buf):
   print(query)
   yam['query'] = buf.getvalue()

但我只是用转义字符返回字符串。

python python-3.x escaping yaml pyyaml
1个回答
0
投票

使用折叠标量可能不是你想要的,因为根据spec

折叠允许在单个空格字符分隔两个非空格字符的任何地方打破长行。

你有这样的线条,但不是全部。

此外,您的输出无效YAML,您需要将折叠线至少缩进一个空格。 (只有当它是文档中的唯一节点时,您不必缩进折叠或文字标量的唯一时间。)

最后因为你只使用>,你会在加载值的末尾有一个换行符,即在分号之后,原始语中没有。


我建议你选择文字标量,其中每个换行符都是换行符。如果您的文件位于input.yaml中,则以下将处理与您设置的条件匹配的任何值行:

import sys
from pathlib import Path
import ruamel.yaml

def try_convert(s):
    """return None if not converted"""
    if 'SELECT' not in s:
        return None
    if '\n' not in s:
        return None
    return ruamel.yaml.scalarstring.LiteralScalarString(s)

def recurse(d):
    """this walks recursively over the datastructure you loaded, entering elements of list, 
       and values of mappings
    """
    if isinstance(d, dict):
        for k in d:
            v = d[k]
            res = try_convert(v)
            if res is not None:
                d[k] = res
            else:
                recurse(d[k])
    elif isinstance(d, list):
        for idx, elem in enumerate(d):
            res = try_convert(elem)
            if res is not None:
                d[idx] = res
            else:
                recurse(d)
    # nothing to do for scalars, which means a scalar in the root of a document will not be converted

file_name = Path('input.yaml')

yaml = ruamel.yaml.YAML()
data = yaml.load(file_name)
recurse(data)
yaml.dump(data, sys.stdout)

这使:

query: |-
  SELECT
    *
  FROM
    (SELECT
    'apple' AS fruit,
    'carrot' AS vegetable);

在文字样式指示符(-)之后的条带选择指示符(|)在该标量的末尾删除任意数量的换行符,因此在加载时,在分号后将没有额外的换行符。

你当然可以在转换中调用一些SQL prettyprinter。只要它的输出是有效的SQL并包含换行符,你可以将它传递给LiteralScalarString并从try_convert()返回它

© www.soinside.com 2019 - 2024. All rights reserved.