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

example 1 - all strings use double quotes; example 2 - no strings (except the last two) use quotes; the YAML cookbook says: Enclosing strings in double quotes allows you to use escaping to represent ASCII and Unicode characters. Does this mean I need to use double quotes only when I want to escape some characters? If yes - why do they use double quotes everywhere in the first example - only for the sake of unity / stylistic reasons? the last two lines of example 2 use ! - the non-specific tag, while the last two lines of the first example don't - and they both work.

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

是否可以说:

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


当前回答

在使用Docker开发Rails应用程序时,我就有这个顾虑。

我最喜欢的方法是一般不使用引号。这包括不使用引号:

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

然而,对于需要转换为字符串的整数值,我使用双引号:

Docker-compose类似版本:"3.8" 端口号如“8080:8080” 形象”traefik: v2.2.1”

但是,对于特殊情况,如布尔值、浮点数、整数和其他情况,在其中使用双引号的条目值可能被解释为字符串,请不要使用双引号。

下面是一个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

这是所有。

我希望这对你们有帮助

其他回答

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,你不需要为布尔值使用引号。 只有版本需要报价。

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

In general, you don't need quotes. Use quotes to force a string, e.g. if your key or value is 10 but you want it to return a String and not a Fixnum, write '10' or "10". Use quotes if your value includes special characters, (e.g. :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, \). Single quotes let you put almost any character in your string, and won't try to parse escape codes. '\n' would be returned as the string \n. Double quotes parse escape codes. "\n" would be returned as a line feed character. The exclamation mark introduces a method, e.g. !ruby/sym to return a Ruby symbol.

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

更新

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

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

在使用Docker开发Rails应用程序时,我就有这个顾虑。

我最喜欢的方法是一般不使用引号。这包括不使用引号:

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

然而,对于需要转换为字符串的整数值,我使用双引号:

Docker-compose类似版本:"3.8" 端口号如“8080:8080” 形象”traefik: v2.2.1”

但是,对于特殊情况,如布尔值、浮点数、整数和其他情况,在其中使用双引号的条目值可能被解释为字符串,请不要使用双引号。

下面是一个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 }}'

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

foo: barbaz{{ bam }}

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

foo: '123'

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

foo: bar1baz234
bar: 123baz

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

foo: 'yes'

需要引号,因为它可能被误解为datatype 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中使用括号一样。这是一种糟糕的做法,损害了可读性,并抛弃了不必引用字符串的美妙特性。

下面是一个小函数(没有优化性能),它在需要时用单引号对字符串进行引用,并测试结果是否可以解编组为原始值: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
}