Почему двухсторонний YAML не анализируется как четырехслойный YAML?

Я вижу странное поведение при разборе YAML (с использованием Ruby 2.5/Psych), созданного с использованием двух пробелов. На мой взгляд, тот же файл с четырьмя пробелами в строке работает, как и ожидалось.

Два пространства:

windows:
  - shell:
    panes:
      - echo hello

приводит к следующему хешу:

{"windows"=>[{"shell"=>nil, "panes"=>["echo hello"]}]}

Принимая во внимание использование четырех пробелов:

windows:
    - shell:
        panes:
            - echo hello

результаты в:

{"windows"=>[{"shell"=>{"panes"=>["echo hello"]}}]}

Я просто просмотрел спецификацию и не увидел ничего, имеющего отношение к этому вопросу.

Ожидается ли такое поведение? Если так, я был бы очень признателен за ссылки на ресурсы, объясняющие почему.

2 ответа

Решение

Проблема в том, что вы не можете просто заменить каждые два пробела четырьмя пробелами. Это потому, что в этой паре строк:

  - shell:
    panes:

эти два пробела во второй строке:

    panes:
  ^^

Являются сокращением для "- " в строке выше. Если бы вторая строка не была сокращена, то пара строк была бы:

  - shell:
  - panes:

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

    - shell:
      panes:

Итак, если вы расширите только первую пару пробелов в строке "панели:", вы получите:

windows:
    - shell:
      panes:
          - git status

Что правильно парсит к ожидаемому результату.

В то время как решение Уэйна верное, объяснение кажется немного неправильным, поэтому я добавлю мое:

В ЯМЛ - для элементов последовательности блоков (например, ? а также : для блочных отображений) рассматривается как отступ ( спецификация):

Символы "-", "?" И ":", используемые для обозначения записей набора блоков, воспринимаются людьми как часть отступа. Это обрабатывается в каждом конкретном случае соответствующими постановками.

Более того, все коллекции блоков (последовательности и отображения) берут свои отступы от своего первого элемента (поскольку нет явного начального индикатора). Так в линии - shell:, - определяет уровень отступа вновь начатой ​​последовательности, в то же время shell: определяет уровень отступа вновь начатого отображения, который является содержимым элемента последовательности. Обратите внимание, как - рассматривается как отступ для определения уровня отступа отображения.

Теперь вернемся к вашему первому примеру:

windows:
  - shell:
    panes:
      - echo hello

panes: находится на том же уровне, что и shell:, Это означает, что YAML анализирует его как ключ отображения, запущенного shell:Это означает, что ключ shell имеет пустое значение. Значения сопоставления неявных ключей, если они не находятся в одной строке, всегда должны иметь отступ больше, чем соответствующий ключ сопоставления ( спецификация):

Свойства узла блока могут занимать несколько строк. В этом случае они должны иметь отступ не менее чем на один пробел больше, чем в коллекции блоков, независимо от отступа записей коллекции блоков.

OTOH, во втором примере:

windows:
    - shell:
        panes:
            - echo hello

panes: находится на более глубоком уровне отступа по сравнению с shell:, Это означает, что он анализируется как значение ключа shell и, таким образом, запускает новое, вложенное отображение блоков.

Наконец, имейте в виду, что с - рассматривается как часть отступа, "отступ двух пробелов" также может означать следующее:

windows:
- shell:
    panes:
    - echo hello

Обратите внимание, как - не более отступ, чем их ключи сопоставления. Это работает, потому что спецификация говорит:

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

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