Нужны ли кавычки для строк в YAML?

Я пытаюсь написать словарь YAML для интернационализации проекта Rails. Я немного растерялся, хотя в некоторых файлах я вижу строки в двойных кавычках, а в некоторых - без. Несколько моментов для рассмотрения:

  • пример 1 - все строки используют двойные кавычки;
  • пример 2 - без строк (кроме двух последних) используются кавычки;
  • Поваренная книга YAML гласит: Заключение строк в двойные кавычки позволяет использовать экранирование для представления символов ASCII и Unicode. Означает ли это, что мне нужно использовать двойные кавычки только тогда, когда я хочу экранировать некоторые символы? Если да - почему они используют двойные кавычки везде в первом примере - только ради единства / стилистических соображений?
  • последние две строки примера 2 используют ! - неспецифический тег, в то время как последние две строки первого примера - нет, и они оба работают.

Мой вопрос: каковы правила использования различных типов цитат в YAML?

Можно ли сказать, что:

  • в общем, вам не нужны кавычки;
  • если вы хотите экранировать символы, используйте двойные кавычки;
  • использование ! с одинарными кавычками, когда...?!?

8 ответов

Решение

После краткого обзора поваренной книги YAML, процитированной в этом вопросе, и некоторого тестирования, вот моя интерпретация:

  • В общем, вам не нужны кавычки.
  • Используйте кавычки, чтобы вызвать строку, например, если ваш ключ или значение 10 но вы хотите, чтобы он возвращал String, а не Fixnum, напишите '10' или же "10",
  • Используйте кавычки, если ваше значение содержит специальные символы (например, :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, \).
  • Одинарные кавычки позволяют вам поместить в строку практически любой символ и не будут пытаться анализировать escape-коды. '\n' будет возвращен как строка \n,
  • Двойные кавычки разбирают escape-коды. "\n" будет возвращен как символ перевода строки.
  • Восклицательный знак вводит метод, например, !ruby/sym вернуть рубиновый символ.

Мне кажется, что лучшим подходом было бы не использовать кавычки без необходимости, а затем использовать одинарные кавычки, если вы специально не хотите обрабатывать escape-коды.

Обновить

"Да" и "Нет" должны быть заключены в кавычки (одинарные или двойные), иначе они будут интерпретированы как значения TrueClass и FalseClass:

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

В то время как ответ Марка хорошо резюмирует, когда кавычки необходимы в соответствии с правилами языка YAML, я думаю, что многие разработчики / администраторы спрашивают себя, работая со строками в YAML, «каким должно быть мое практическое правило для обработки строк. ?"

Это может показаться субъективным, но количество правил, которые вы должны запомнить, если вы хотите использовать кавычки только тогда, когда они действительно необходимы в соответствии со спецификацией языка , несколько чрезмерно для такой простой вещи, как указание одного из наиболее распространенных типов данных. . Не поймите меня неправильно, вы в конечном итоге будете помнить их при регулярной работе с YAML, но что, если вы используете его время от времени, и вы не развили автоматизм для написания YAML? Вы действительно хотите потратить время на запоминание всех правил, просто чтобы правильно указать строку?

Весь смысл «практического правила» состоит в том, чтобы сохранить когнитивные ресурсы и справиться с общей задачей, не задумываясь о ней. Наше "процессорное" время, вероятно, можно использовать для чего-то более полезного, чем правильная обработка строк.

С этой - чисто практической - точки зрения, я считаю, что лучшим практическим правилом является использование строк в одинарных кавычках. Обоснование этого:

  • Строки в одинарных кавычках работают для всех сценариев, кроме случаев, когда вам нужно использовать escape-последовательности.
  • Единственный специальный символ, который вы должны обрабатывать в строке, заключенной в одинарные кавычки, - это сама одинарная кавычка.

Это всего лишь 2 правила, которые следует помнить некоторым случайным пользователям YAML, сводя к минимуму когнитивные усилия.

На этот вопрос есть несколько отличных ответов. Однако я хотел бы расширить их и предоставить некоторый контекст из новой официальной спецификации YAML v1.2.2 (выпущенной 1 октября 2021 года), которая является «истинным источником» всего, что касается YAML.

Для представления строк можно использовать три разных стиля, каждый из которых имеет свои (отрицательные) преимущества:

YAML предоставляет три скалярных стиля потока: двойные кавычки, одиночные кавычки и простой (без кавычек). Каждый из них обеспечивает различный компромисс между удобочитаемостью и выразительностью.

Стиль с двойными кавычками:

  • Стиль двойных кавычек определяется окружающими индикаторами. Это единственный стиль, способный выражать произвольные строки с помощью управляющих последовательностей. Это происходит за счет экранирования символов и.

Стиль в одинарных кавычках:

  • Стиль в одинарных кавычках определяется окружающими индикаторами. Следовательно, в скаляре, заключенном в одинарные кавычки, такие символы необходимо повторять. Это единственная форма экранирования, выполняемая в скалярах, заключенных в одинарные кавычки. В частности, можно свободно использовать символы и. Это ограничивает скаляры в одинарных кавычках печатными символами. Кроме того, можно разорвать только длинную строку в одинарных кавычках, если пробел окружен непробелами.

Простой (без кавычек) стиль:

  • Простой (без кавычек) стиль не имеет идентифицирующих индикаторов и не обеспечивает формы экранирования. Таким образом, это наиболее читаемый, ограниченный и наиболее контекстно-зависимый стиль. Помимо ограниченного набора символов, простой скаляр не должен быть пустым или содержать начальные или конечные символы пробела. Разорвать можно только длинную простую строку, в которой пробел окружен непробелами. Обычные скаляры не должны начинаться с большинства индикаторов, так как это может вызвать неоднозначность с другими конструкциями YAML. Однако :, ? а также - индикаторы могут использоваться в качестве первого символа, если за ним следует «безопасный» символ без пробела, так как это не вызывает двусмысленности.

TL;DR

При этом, согласно официальной спецификации YAML, следует :

  • По возможности используйте стиль без кавычек, так как он наиболее читаемый.
  • Используйте стиль в одинарных кавычках ( '), если такие символы, как и \ используются внутри строки, чтобы избежать их передачи и, следовательно, улучшить читаемость.
  • Используйте стиль двойных кавычек ( "), когда первых двух опций недостаточно, то есть в сценариях, где требуются более сложные разрывы строк или требуются непечатаемые символы.

Ответ, отмеченный как правильный, вводит в заблуждение. (Хотя это объясняет ямл, с которым можно встретиться в дикой природе)

Строки в yaml нуждаются в кавычках только в том случае, если (начало) значение может быть неверно истолковано как тип данных или значение содержит «:» (потому что оно может быть неверно истолковано как ключ).

Например

      foo: '{{ bar }}'

нужны кавычки, потому что это может быть неверно истолковано как тип данных dict, но

      foo: barbaz{{ bam }}

нет, так как он не начинается с критического символа. Следующий,

      foo: '123'

нужны кавычки, потому что это может быть неверно истолковано как тип данных, но

      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. Это плохая практика, вредит удобочитаемости и отбрасывает прекрасную возможность не заключать строки в кавычки. Пожалуйста, прочтите документацию, прежде чем распространять ложные знания.

У меня возникла эта проблема, когда я работал над приложением Rails с Docker.

Мой наиболее предпочтительный подход - вообще не использовать кавычки. Это включает отказ от использования кавычек для:

  • такие переменные, как ${RAILS_ENV}
  • значения разделены двоеточием (:) как postgres-log:/var/log/postgresql
  • другие значения строк

Однако я использую двойные кавычки для integer значения, которые необходимо преобразовать в такие строки, как:

  • версия для докеров, например version: "3.8"
  • номера портов, такие как "8080:8080"

Однако для особых случаев, таких как booleans, floats, integers, и другие случаи, когда использование двойных кавычек для значений записи может быть интерпретировано как 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

Вот и все.

надеюсь, это поможет

Вот небольшая функция (не оптимизированная для производительности), которая при необходимости заключает ваши строки в одинарные кавычки и проверяет, можно ли преобразовать результат в исходное значение: 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
}

Если вы пытаетесь избежать строки в таверне pytest, !raw может быть полезно, чтобы избежать синтаксического анализа строк в yaml:

      some: !raw "{test: 123}"

Проверьте дополнительную информацию:https://tavern.readthedocs.io/en/latest/basics.html#type-conversions.

      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, вам не нужно использовать цитату для логического значения.
Только версия нуждается в цитатах.

Другие вопросы по тегам