YAML:在YAML中字符串需要引号吗?

我正在尝试为Rails项目的国际化编写YAML字典。我有点困惑,因为在一些文件中,我看到字符串在双引号中,而在一些文件中没有。以下几点需要考虑:

  • 示例1 -所有字符串使用双引号;
  • 示例2 -没有字符串(除了最后两个)使用引号;
  • 这是否意味着我需要使用双引号,只有当我想转义一些字符?如果是的话——为什么他们在第一个例子中到处使用双引号——仅仅是为了统一/风格的原因?
  • 例2的最后两行使用!——非特定标记,而第一个示例的最后两行不使用——它们都可以工作。

我的问题是:在YAML中使用不同类型的引号的规则是什么?

是否可以说:

  • 一般来说,你不需要引用;
  • 如果你想转义字符,请使用双引号;
  • 使用!和单引号,当…?!?
355523 次浏览

在简要回顾了问题中引用的YAML烹饪书并进行了一些测试之后,以下是我的解释:

  • 一般来说,你不需要引用。
  • 使用引号强制字符串,例如,如果你的键或值是10,但你想让它返回string而不是Fixnum,那么写'10'"10"
  • 如果你的值包含特殊字符,请使用引号(例如:{}[],&*#?{0, {2, {3, {4, {5, {6, {7, {8)。
  • 单引号允许您在字符串中放入几乎任何字符,并且不会尝试解析转义码。'\n'将作为字符串\n返回。
  • 双引号解析转义码。"\n"将作为换行字符返回。
  • 感叹号引入了一个方法,例如!ruby/sym来返回Ruby符号。

在我看来,最好的方法是除非必要,否则不要使用引号,然后使用单引号,除非特别想处理转义码。

# EYZ0

“Yes”和“No”应该用双引号括起来(单引号或双引号),否则它们将被解释为TrueClass和FalseClass值:

en:
yesno:
'yes': 'Yes'
'no': 'No'

在使用码头工人开发Rails应用程序时,我就有这个顾虑。

我最喜欢的方法通常是使用引号。这包括使用引号的:

  • 变量,如${RAILS_ENV}
  • 用冒号(:)分隔的值,如postgres-log:/var/log/postgresql
  • 其他字符串值

然而,我使用双引号的integer值,需要转换为字符串,如:

  • docker-compose版本,如version: "3.8"
  • 端口号,如"8080:8080"
  • 图片# EYZ0

但是,对于特殊情况,如booleansfloatsintegers和其他情况,其中使用双引号的条目值可以解释为strings,请使用双引号的

下面是一个示例docker-compose.yml文件来解释这个概念:

version: "3"


services:
traefik:
image: "traefik:v2.2.1"
command:
- --api.insecure=true # Don't do that in production
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro

这是所有。

我希望这对你们有帮助

yaml中的字符串只有在(开头)的值可能会被误解为数据类型或值包含":"(因为它可能会被误解为钥匙)。

例如

foo: '\{\{ bar }}'

需要引号,因为它可能被误解为数据类型dict,但是

foo: barbaz\{\{ bam }}

不,因为它不是以关键字符开头的。接下来,

foo: '123'

需要引号,因为它可能被误解为数据类型int,但是

foo: bar1baz234
bar: 123baz

不是,因为它不能被误解为int

foo: 'yes'

需要引号,因为它可能被误解为数据类型bool

foo: "bar:baz:bam"

需要引号,因为该值可能被误解为键。

这些只是例子。使用yamllint有助于避免使用错误的标记开始值

foo@bar:/tmp$ yamllint test.yaml
test.yaml
3:4       error    syntax error: found character '@' that cannot start any token (syntax)

并且是必须的,如果与yaml有效地工作。

像一些人建议的那样引用所有字符串,就像在python中使用括号一样。这是一种糟糕的做法,损害了可读性,并抛弃了不必引用字符串的美妙特性。

虽然Mark的回答很好地总结了根据YAML语言规则,当引号是需要时,我认为许多开发人员/管理员都在问自己,当在YAML中处理字符串时,是“应该我的处理字符串的经验法则是什么?”

这听起来可能是主观的,但是如果您想要使用引号只有而实际上是需要按照语言规范,那么对于指定最常见的数据类型之一这样简单的事情来说,您必须记住的规则数量有点太多了。不要误解我的意思,当您经常使用YAML时,您最终会记住它们,但是如果您偶尔使用它,并且您没有开发编写YAML的自动性呢?你真的想花时间记住所有的规则,只是为了正确地指定字符串吗?

“经验法则”的全部意义在于;就是节省认知资源,不假思索地处理一项普通任务。我们的“CPU"时间可以用在比正确处理字符串更有用的事情上。

从这个纯粹实用的角度来看,我认为最好的经验法则是对字符串进行单引号。它背后的原理是:

  • 单引号字符串适用于所有场景,除非需要使用转义序列。
  • 在单引号字符串中必须处理的唯一特殊字符是单引号本身。

对于一些偶尔使用YAML的用户来说,这只是需要记住的2条规则,可以最大限度地减少认知工作量。

如果你想在pytest tavern中转义字符串,!raw可能有助于避免将字符串解析到yaml:

some: !raw "{test: 123}"

查看更多信息 # EYZ0 < / p >

这个问题有一些很好的答案。 然而,我想扩展它们并提供new官方YAML v1.2.2规范(2021年10月1日发布)的一些背景,这是“真正的来源”。

.

.

有三种不同的风格可以用来表示字符串,每一种都有自己的(缺点)优点:

YAML提供了三种流标量样式:双引号、单引号和普通(不加引号)。每一种都在可读性和表现力之间提供了不同的权衡。

# EYZ0:

  • 双引号样式是通过围绕"指示符指定的。通过使用\转义序列,这是唯一能够表示任意字符串的样式。这是以必须转义\"字符为代价的。

# EYZ0:

  • 单引号样式是通过围绕'指示符指定的。因此,在单引号标量中,这样的字符需要重复。这是在单引号标量中执行转义的唯一形式。特别地,\"字符可以自由使用。这将单引号标量限制为可打印字符。此外,只有在空格字符被非空格包围的长单引号行中才有可能换行。

# EYZ0:

  • plain(未加引号)样式没有标识指示符,也不提供转义形式。因此,它是最有可读性、最受限制和最上下文敏感的风格。除了受限制的字符集外,普通标量不能为空或包含前导或尾随空白字符。只有在空格字符被非空格字符包围的情况下,才有可能断行。 普通标量不能以大多数指示符开头,因为这会与其他YAML构造产生歧义。但是,:?-可以作为第一个字符,如果后面跟着一个非空格的“安全”字符,因为这样不会造成歧义

博士TL;

话虽如此,根据官方YAML规范,应该这样做:

  • 只要适用,就使用不加引号的样式,因为它是最易读的。
  • 如果字符串中使用了"\这样的字符,则使用单引号样式(')来避免转义,从而提高可读性。
  • 当前两个选项还不够时,例如需要更复杂的换行符或需要不可打印字符时,请使用双引号样式(")。
这里有一个小函数(没有优化性能),它在需要时用单引号引用字符串,并测试结果是否可以被解组为原始值:https://go.dev/play/p/AKBzDpVz9hk。 它不是测试规则,而是简单地使用编组程序本身,并检查编组和反编组的值是否与原始版本匹配
func yamlQuote(value string) string {
input := fmt.Sprintf("key: %s", value)


var res struct {
Value string `yaml:"key"`
}


if err := yaml.Unmarshal([]byte(input), &res); err != nil || value != res.Value {
quoted := strings.ReplaceAll(value, `'`, `''`)
return fmt.Sprintf("'%s'", quoted)
}


return value
}
version: "3.9"


services:
seunggabi:
image: seunggabi:v1.0.0
command:
api:
insecure: true
ports:
- 80:80
- 8080:8080
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
docker compoese up docker-compose.yaml

如果你使用docker compose v2,你不需要为boolean使用引号。

.只有版本需要引用