【问题标题】:Having issues escaping single quote转义单引号时遇到问题
【发布时间】:2019-10-07 19:07:45
【问题描述】:

使用 ruamel.yaml 向 yaml 添加新值时,我很难转义单引号。

下面是我正在做的事情

import sys
from ruamel.yaml import YAML

yaml_doc = """\
Mappings:
  Values:
    '123': 'no'
"""

yaml = YAML()
yaml.preserve_quotes = True
data = yaml.load(yaml_doc)

new_value = data['Mappings']['Values']
new_value.insert(len(new_value), '456','' 'no'' ', comment="New Value")
new_value.insert(len(new_value), '789',' ''no' '', comment="New Value 2")
yaml.dump(data, sys.stdout)

使用此代码,我总是在我插入的值的 no 之后/之前得到一个前导或尾随空格。

Mappings:
  Values:
    '123': 'no'
    '456': 'no '  # New Value
    '789': ' no' # New Value 2

如何插入带单引号但没有尾随/标题空格的 no 值?

【问题讨论】:

标签: python yaml ruamel.yaml


【解决方案1】:

更新:@Anthon 告诉我,考虑到 no,早期版本的 YAML 会将 no'no' 视为不同的值成为一个布尔值。因此,请仅将我在下面所说的内容应用于当前版本的 YAML。此外,除了编写 YAML 之外,也许还有另一个动机,它将从最新的解析器中产生特定的结果。在这种情况下,您可以从@Anthon 那里得到一个很好的答案,即如何通过无法考虑旧 YAML 格式的编写器将这些引号强制转换为生成的 YAML(我建议确保没有这样的作家模式)。

YAML 是关于传达一种特定的数据结构,包括字典、列表和值。解析 YAML 时,您只关心生成的数据结构。如果两个 YAML 文件不同但产生相同的数据结构,那么差异对您来说应该没有关系。

在这里,我不确定 OP 想要什么。看来他要么希望单词 no 在他的 YAML 表示的数据结构中出现几次,或者他希望 'no' 成为最终出现在数据结构中。以下是最简洁的编写方式(在 YAML 1.2 中):

== no

'不' == "'no'"

这里没有字符 'no' 需要以 OP 试图强制的方式出现在 YAML 中的情况。所有这些额外的代码都试图在不需要时将这些字符强制输入 YAML。该构造与no 的含义相同。忘记引号就行了。

【讨论】:

    【解决方案2】:

    我不确定我是否完全理解您的要求,但您只是插入了 3 个字符串作为值并将它们连接起来。在

    new_value.insert(len(new_value), '456','' 'no'' ', comment="New Value")
    

    '' 'no'' ' 部分转换为 ''=<Empty String> 'no'=no ' '=<Space>

    所以如果你想要一个普通的'no' 就这样做:

    new_value.insert(len(new_value), '456','no', comment="New Value")
    

    【讨论】:

    • 这并没有在他的 YAML 文档中提供 OP 'no',因为他明确要求(见帖子的最后一行),而只是 no
    • 可以通过new_value.insert(len(new_value), '456','\'no\'', comment="New Value")轻松调整
    • 这实际上会让你在 YAML 文档中得到"'no'"。尽管这些是 no 周围的单引号,但我认为 OP 希望这些行看起来与他的输入文档的最后一个相似。
    • 你确定new_value.insert(len(new_value), '456','no', comment="New Value")不会做他想做的事吗?他在yaml.preserve_quotes = True上有这个标志
    • 是的,我确定。 1) 保留仅适用于从 YAML 文档加载的内容(首先必须保留它) 2) 我非常熟悉 ruamel.yaml 的内部结构。 3)我尝试了代码,然后在我之前的评论中复制粘贴了结果;-)
    【解决方案3】:

    如果你愿意尝试:

    print(repr('' 'no'' '))
    

    它会给你:

    'no '
    

    您所做的是将字符串 '' 与字符串 'no' 并置 字符串' ',Python 只是在调用print 之前将其连接到'no '。你什么 正在尝试做的是使用 YAML 单引号标量转义机制 在 Python 中,只有在你 YAML().load() 来自 YAML 的字符串时才有效。

    如果你想在输出中使用单引号标量,就像你有 在您的输入中,您应该使标量与您得到的类型相同 使用.load()。那是 ruamel.yaml.scalarstring.SingleQuotedScalarString(如string 子类)。

    import sys
    from ruamel.yaml import YAML
    from ruamel.yaml.scalarstring import SingleQuotedScalarString as sq
    
    yaml_doc = """\
    Mappings:
      Values:
        '123': 'no'
    """
    
    yaml = YAML()
    yaml.preserve_quotes = True
    data = yaml.load(yaml_doc)
    
    new_value = data['Mappings']['Values']
    new_value['456'] = sq('no')
    new_value.yaml_add_eol_comment(comment="New Value", key='456', column=0)
    new_value.insert(len(new_value), '789', sq('no'), comment="New Value 2")
    yaml.dump(data, sys.stdout)
    

    这给出了:

    Mappings:
      Values:
        '123': 'no'
        '456': 'no' # New Value
        '789': 'no' # New Value 2
    

    【讨论】:

    • 第一个附加值需要使用yaml_add_eol_comment,否则会在注释前获得额外的空格(并且.insert 没有设置列的选项)。不知道那里发生了什么,可能是一个小错误。
    • 我不明白你为什么要经历所有这些工作才能在 YAML 中使用 'no'no。他们的意思是一样的。这就是为什么这个练习对你和其他人来说都很难理解。在任何一种情况下,当解析文件时,您最终都会得到数量 no,没有引号。如果你了解 YAML 语法,这一切都变得非常简单。
    • 除了由适当的 YAML 解释器解析时会产生什么之外,您是否有理由关心 YAML 中的内容?您是否希望得到 YAML 解析器读取的数量 'no' 并与引号一起保存?目前不会发生这种情况。
    • @Steve 您的评论中有多个虚假声明。对于正确的、最新的 YAML 解析,它们意味着同样的事情,例如ruamel.yaml 和其他 YAML 1.2 解析器。尽管该规范已经发布了十年,但一些人和项目仍然使用基于 YAML 1.1 规范的解析器,对于那些 no 加载为布尔值,'no' 加载为字符串。在 load-modify-dump 上保留这样的引用,无论是为了美观还是为了防止在修订控制下的文件中出现虚假更改,如果您使用 ruamel.yaml,当前会发生
    • @Anthon,这些都是好点。尽管就当前的 YAML 规范而言,我的 cmets 中没有虚假声明。我确实犯了不允许旧版本的 YAML 可能不同的错误。谢谢你在那里教育我。我仍然认为以这种方式编写一个简单的 YAML 文件看起来像代码异味。至于签入生成的 YAML 文件,这违反了 DRY 原则。但在这一切中,我不允许有充分的理由去做这一切。因此,我的第二条评论是一个问题,您正在回答这个问题。
    猜你喜欢
    • 2013-07-07
    • 1970-01-01
    • 2020-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 2021-11-11
    相关资源
    最近更新 更多