Как я могу проанализировать YAML файл из оболочки Linux script?

Я хочу предоставить структурированный файл конфигурации, который максимально упрощен для нетехнического пользователя для редактирования (к сожалению, он должен быть файлом), и поэтому я хотел использовать YAML. Я не могу найти способ разбора этого из оболочки Unix script.

Ответ 1

Мой вариант использования может быть или не быть таким же, как то, что задавал этот оригинальный пост, но он определенно похож.

Мне нужно вытащить некоторый YAML в качестве переменных bash. YAML никогда не будет более одного уровня.

YAML выглядит так:

KEY:                value
ANOTHER_KEY:        another_value
OH_MY_SO_MANY_KEYS: yet_another_value
LAST_KEY:           last_value

Выход вроде-a dis:

KEY="value"
ANOTHER_KEY="another_value"
OH_MY_SO_MANY_KEYS="yet_another_value"
LAST_KEY="last_value"

Я достиг результата с этой строкой:

sed -e 's/:[^:\/\/]/="/g;s/$/"/g;s/ *=/=/g' file.yaml > file.sh
  • s/:[^:\/\/]/="/g находит : и заменяет его на =", игнорируя :// (для URL-адресов)
  • s/$/"/g добавляет " в конец каждой строки
  • s/ *=/=/g удаляет все пробелы перед =

Ответ 2

Вот bash -одно парсер, который использует sed и awk для анализа простых файлов yaml:

function parse_yaml {
   local prefix=$2
   local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
   sed -ne "s|^\($s\):|\1|" \
        -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \
        -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p"  $1 |
   awk -F$fs '{
      indent = length($1)/2;
      vname[indent] = $2;
      for (i in vname) {if (i > indent) {delete vname[i]}}
      if (length($3) > 0) {
         vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
         printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
      }
   }'
}

Он понимает такие файлы, как:

## global definitions
global:
  debug: yes
  verbose: no
  debugging:
    detailed: no
    header: "debugging started"

## output
output:
   file: "yes"

Который при анализе с использованием:

parse_yaml sample.yml

выведет:

global_debug="yes"
global_verbose="no"
global_debugging_detailed="no"
global_debugging_header="debugging started"
output_file="yes"

он также понимает файлы yaml, созданные ruby, которые могут включать в себя символы ruby, например:

---
:global:
  :debug: 'yes'
  :verbose: 'no'
  :debugging:
    :detailed: 'no'
    :header: debugging started
  :output: 'yes'

и будет выводиться так же, как в предыдущем примере.

Типичное использование в script:

eval $(parse_yaml sample.yml)

parse_yaml принимает аргумент префикса, так что все импортированные настройки имеют общий префикс (что уменьшит риск конфликтов пространства имен).

parse_yaml sample.yml "CONF_"

дает:

CONF_global_debug="yes"
CONF_global_verbose="no"
CONF_global_debugging_detailed="no"
CONF_global_debugging_header="debugging started"
CONF_output_file="yes"

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

## global definitions
global:
  debug: yes
  verbose: no
  debugging:
    detailed: no
    header: "debugging started"

## output
output:
   debug: $global_debug

Еще одно приятное использование - сначала проанализировать файл по умолчанию, а затем пользовательские настройки, который работает, поскольку последние настройки переопределяют первые:

eval $(parse_yaml defaults.yml)
eval $(parse_yaml project.yml)

Ответ 3

Я написал shyaml в python для запросов YAML запросов из командной строки оболочки.

Обзор:

$ pip install shyaml      ## installation

Пример файла YAML (со сложными функциями):

$ cat <<EOF > test.yaml
name: "MyName !!"
subvalue:
    how-much: 1.1
    things:
        - first
        - second
        - third
    other-things: [a, b, c]
    maintainer: "Valentin Lab"
    description: |
        Multiline description:
        Line 1
        Line 2
EOF

Основной запрос:

$ cat test.yaml | shyaml get-value subvalue.maintainer
Valentin Lab

Более сложный цикл для сложных значений:

$ cat test.yaml | shyaml values-0 | \
  while read -r -d $'\0' value; do
      echo "RECEIVED: '$value'"
  done
RECEIVED: '1.1'
RECEIVED: '- first
- second
- third'
RECEIVED: '2'
RECEIVED: 'Valentin Lab'
RECEIVED: 'Multiline description:
Line 1
Line 2'

Несколько ключевых моментов:

  • все типы YAML и странности с синтаксисом корректно обрабатываются, как многострочные, цитируемые строки, встроенные последовательности...
  • \0 Доступен расширенный выход для сплошной многострочной манипуляции ввода.
  • простая пунктирная нотация для выбора под-значений (т.е. subvalue.maintainer является допустимым ключом).
  • доступ по индексу предоставляется последовательностям (т.е. subvalue.things.-1 является последним элементом последовательности subvalue.things.)
  • доступ ко всем элементам sequence/structs за один раз для использования в циклах bash.
  • вы можете вывести всю подчасти файла YAML как... YAML, которые хорошо сочетаются для дальнейших манипуляций с shyaml.

Дополнительные примеры и документация доступны на странице shyaml github или shyaml PyPI.

Ответ 4

Можно передать небольшой скрипт некоторым интерпретаторам, таким как Python. Простым способом сделать это с помощью Ruby и его библиотеки YAML является следующее:

$ RUBY_SCRIPT="data = YAML::load(STDIN.read); puts data['a']; puts data['b']"
$ echo -e '---\na: 1234\nb: 4321' | ruby -ryaml -e "$RUBY_SCRIPT"
1234
4321

где data являются хешем (или массивом) со значениями из yaml.

В качестве бонуса он будет разбирать Jekyll front matter просто отлично.

ruby -ryaml -e "puts YAML::load(open(ARGV.first).read)['tags']" example.md

Ответ 5

yq - это легкий и портативный YAML-процессор командной строки

Целью проекта является создание файлов jq или sed из yaml.

(http://mikefarah.github.io/yq/)

В качестве примера (украдено прямо из документации) приведен файл sample.yaml:

---
bob:
  item1:
    cats: bananas
  item2:
    cats: apples

затем

yq r sample.yaml bob.*.cats

будет выводить

- bananas
- apples

Ответ 6

Учитывая, что Python3 и PyYAML - это довольно простые зависимости, встречающиеся в настоящее время, следующие могут помочь:

yaml() {
    python3 -c "import yaml;print(yaml.load(open('$1'))$2)"
}

VALUE=$(yaml ~/my_yaml_file.yaml "['a_key']")

Ответ 7

Сложно сказать, потому что это зависит от того, что вы хотите, чтобы анализатор извлекал из вашего документа YAML. Для простых случаев вы можете использовать grep, cut, awk и т.д. Для более сложного разбора вам потребуется использовать полномасштабную библиотеку синтаксического анализа, такую ​​как Python PyYAML или YAML:: Perl.

Ответ 8

Я просто написал парсер, который я назвал Yay! (Ямл не Ямскле!), Который анализирует Ямслеск, небольшое подмножество ЯМЛ. Итак, если вы ищете 100% -ный синтаксический анализатор YAML для Bash, то это не так. Однако, чтобы указать OP, если вы хотите, чтобы структурированный файл конфигурации был максимально простым для нетехнического пользователя для редактирования, похожим на YAML, это может представлять интерес.

Это воодушевленный более ранним ответом, но пишет ассоциативные массивы (да, для этого требуется Bash 4.x) вместо основных переменных, Он делает это таким образом, что позволяет анализировать данные без предварительного знания ключей, чтобы записывать управляемый данными код.

Как и элементы массива key/value, каждый массив имеет массив keys, содержащий список имен ключей, массив children, содержащий имена дочерних массивов, и ключ parent, который ссылается на его родительский элемент.

Это является примером Ямслеска:

root_key1: this is value one
root_key2: "this is value two"

drink:
  state: liquid
  coffee:
    best_served: hot
    colour: brown
  orange_juice:
    best_served: cold
    colour: orange

food:
  state: solid
  apple_pie:
    best_served: warm

root_key_3: this is value three

Здесь показан пример, показывающий, как его использовать:

#!/bin/bash
# An example showing how to use Yay

. /usr/lib/yay

# helper to get array value at key
value() { eval echo \${$1[$2]}; }

# print a data collection
print_collection() {
  for k in $(value $1 keys)
  do
    echo "$2$k = $(value $1 $k)"
  done

  for c in $(value $1 children)
  do
    echo -e "$2$c\n$2{"
    print_collection $c "  $2"
    echo "$2}"
  done
}

yay example
print_collection example

который выводит:

root_key1 = this is value one
root_key2 = this is value two
root_key_3 = this is value three
example_drink
{
  state = liquid
  example_coffee
  {
    best_served = hot
    colour = brown
  }
  example_orange_juice
  {
    best_served = cold
    colour = orange
  }
}
example_food
{
  state = solid
  example_apple_pie
  {
    best_served = warm
  }
}

И здесь является синтаксический анализатор:

yay_parse() {

   # find input file
   for f in "$1" "$1.yay" "$1.yml"
   do
     [[ -f "$f" ]] && input="$f" && break
   done
   [[ -z "$input" ]] && exit 1

   # use given dataset prefix or imply from file name
   [[ -n "$2" ]] && local prefix="$2" || {
     local prefix=$(basename "$input"); prefix=${prefix%.*}
   }

   echo "declare -g -A $prefix;"

   local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
   sed -n -e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
          -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$input" |
   awk -F$fs '{
      indent       = length($1)/2;
      key          = $2;
      value        = $3;

      # No prefix or parent for the top level (indent zero)
      root_prefix  = "'$prefix'_";
      if (indent ==0 ) {
        prefix = "";          parent_key = "'$prefix'";
      } else {
        prefix = root_prefix; parent_key = keys[indent-1];
      }

      keys[indent] = key;

      # remove keys left behind if prior row was indented more than this row
      for (i in keys) {if (i > indent) {delete keys[i]}}

      if (length(value) > 0) {
         # value
         printf("%s%s[%s]=\"%s\";\n", prefix, parent_key , key, value);
         printf("%s%s[keys]+=\" %s\";\n", prefix, parent_key , key);
      } else {
         # collection
         printf("%s%s[children]+=\" %s%s\";\n", prefix, parent_key , root_prefix, key);
         printf("declare -g -A %s%s;\n", root_prefix, key);
         printf("%s%s[parent]=\"%s%s\";\n", root_prefix, key, prefix, parent_key);
      }
   }'
}

# helper to load yay data file
yay() { eval $(yay_parse "[email protected]"); }

В связанном исходном файле есть документация, а ниже приведено краткое описание того, что делает код.

Функция yay_parse сначала находит файл input или завершает работу с состоянием выхода из 1. Затем он определяет набор данных prefix, явно заданный или полученный из имени файла.

Он записывает правильные команды bash на свой стандартный вывод, который, если выполняется, определяет массивы, представляющие содержимое файла входных данных. Первый из них определяет массив верхнего уровня:

echo "declare -g -A $prefix;"

Обратите внимание, что объявления массива ассоциативны (-A), что является признаком Bash версии 4. Объявления также глобальны (-g), поэтому они могут быть выполнены в функции, но доступны для глобальной области, например помощник yay:

yay() { eval $(yay_parse "[email protected]"); }

Входные данные изначально обрабатываются с помощью sed. Он отбрасывает строки, которые не соответствуют спецификации формата Ямслеска, прежде чем ограничивать действительные поля Ямслеска символом ASCII File Separator и удалять любые двойные кавычки окружая поле значений.

 local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
 sed -n -e "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
        -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$input" |

Два выражения похожи; они отличаются только тем, что первый выбирает цитированные значения, где второй выбирает некотируемые.

File Separator (28/hex 12/восьмеричный 034) используется, потому что, как непечатаемый символ, вряд ли во входных данных.

Результат передается по каналу в awk, который обрабатывает его вход по одной строке за раз. Он использует символ FS для назначения каждому полю переменной:

indent       = length($1)/2;
key          = $2;
value        = $3;

Все строки имеют отступ (возможно, ноль) и ключ, но все они не имеют значения. Он вычисляет уровень отступа для строки, делящей длину первого поля, содержащего ведущие пробелы, на два. Элементы верхнего уровня без какого-либо отступ находятся на нулевом уровне.

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

root_prefix  = "'$prefix'_";
if (indent ==0 ) {
  prefix = "";          parent_key = "'$prefix'";
} else {
  prefix = root_prefix; parent_key = keys[indent-1];
}

parent_key - это ключ на уровне отступа выше текущего уровня отступа строки и представляет коллекцию, частью которой является текущая строка. Группы ключей/значений коллекции будут храниться в массиве с его именем, определенным как конкатенация prefix и parent_key.

Для верхнего уровня (нулевой уровень отступа) префикс набора данных используется в качестве родительского ключа, поэтому он не имеет префикса (он установлен в ""). Все остальные массивы имеют префикс корня.

Затем текущий ключ вставляется в массив (awk-internal), содержащий ключи. Этот массив сохраняется на протяжении всей сессии awk и поэтому содержит ключи, вставленные предыдущими строками. Ключ вставляется в массив, используя его отступ в качестве индекса массива.

keys[indent] = key;

Поскольку этот массив содержит ключи от предыдущих строк, все клавиши с уровнем углубления уровня, отличным от текущего уровня отступа строки, удаляются:

 for (i in keys) {if (i > indent) {delete keys[i]}}

Это оставляет массив ключей, содержащий цепочку ключей от корня на уровне отступа 0 до текущей строки. Он удаляет устаревшие ключи, которые остаются, когда предыдущая строка была отступом глубже, чем текущая строка.

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

Имя коллекции представляет собой конкатенацию текущей строки prefix и parent_key.

Когда ключ имеет значение, клавиша с этим значением назначается текущей коллекции следующим образом:

printf("%s%s[%s]=\"%s\";\n", prefix, parent_key , key, value);
printf("%s%s[keys]+=\" %s\";\n", prefix, parent_key , key);

Первый оператор выводит команду для присвоения значения ассоциативному элементу массива, названному после ключа, а второй выводит команду на добавление ключа в список keys, ограниченный коллекцией:

<current_collection>[<key>]="<value>";
<current_collection>[keys]+=" <key>";

Если ключ не имеет значения, запускается новая коллекция следующим образом:

printf("%s%s[children]+=\" %s%s\";\n", prefix, parent_key , root_prefix, key);
printf("declare -g -A %s%s;\n", root_prefix, key);

Первый оператор выводит команду для добавления новой коллекции в текущий список с ограниченным пространством children, а второй выводит команду для объявления нового ассоциативного массива для новой коллекции:

<current_collection>[children]+=" <new_collection>"
declare -g -A <new_collection>;

Весь вывод из yay_parse может быть проанализирован как команды Bash с помощью встроенных команд Bash eval или source.

Ответ 9

вот расширенная версия ответа Стефана Фарештама:

function parse_yaml {
   local prefix=$2
   local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
   sed -ne "s|,$s\]$s\$|]|" \
        -e ":1;s|^\($s\)\($w\)$s:$s\[$s\(.*\)$s,$s\(.*\)$s\]|\1\2: [\3]\n\1  - \4|;t1" \
        -e "s|^\($s\)\($w\)$s:$s\[$s\(.*\)$s\]|\1\2:\n\1  - \3|;p" $1 | \
   sed -ne "s|,$s}$s\$|}|" \
        -e ":1;s|^\($s\)-$s{$s\(.*\)$s,$s\($w\)$s:$s\(.*\)$s}|\1- {\2}\n\1  \3: \4|;t1" \
        -e    "s|^\($s\)-$s{$s\(.*\)$s}|\1-\n\1  \2|;p" | \
   sed -ne "s|^\($s\):|\1|" \
        -e "s|^\($s\)-$s[\"']\(.*\)[\"']$s\$|\1$fs$fs\2|p" \
        -e "s|^\($s\)-$s\(.*\)$s\$|\1$fs$fs\2|p" \
        -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \
        -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" | \
   awk -F$fs '{
      indent = length($1)/2;
      vname[indent] = $2;
      for (i in vname) {if (i > indent) {delete vname[i]; idx[i]=0}}
      if(length($2)== 0){  vname[indent]= ++idx[indent] };
      if (length($3) > 0) {
         vn=""; for (i=0; i<indent; i++) { vn=(vn)(vname[i])("_")}
         printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, vname[indent], $3);
      }
   }'
}

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

global:
  input:
    - "main.c"
    - "main.h"
  flags: [ "-O3", "-fpic" ]
  sample_input:
    -  { property1: value, property2: "value2" }
    -  { property1: "value3", property2: 'value 4' }

производит этот вывод:

global_input_1="main.c"
global_input_2="main.h"
global_flags_1="-O3"
global_flags_2="-fpic"
global_sample_input_1_property1="value"
global_sample_input_1_property2="value2"
global_sample_input_2_property1="value3"
global_sample_input_2_property2="value 4"

как вы можете видеть - элементы автоматически нумеруются, чтобы получить разные имена переменных для каждого элемента. В bash нет многомерных массивов, так что это один из способов обхода. Несколько уровней поддерживаются. Чтобы обойти проблему с конечными пробелами, упомянутую @briceburg, нужно заключить значения в одинарные или двойные кавычки. Тем не менее, есть некоторые ограничения: Расширение словарей и списков может давать неправильные результаты, если значения содержат запятые. Кроме того, более сложные структуры, такие как значения, охватывающие несколько строк (например, ssh-ключи), (пока) не поддерживаются.

Несколько слов о коде: Первая команда sed расширяет краткую форму словарей { key: value,...} до обычных и преобразует их в более простой стиль yaml. Второй вызов sed делает то же самое для кратких обозначений списков и преобразует [ entry,... ] в подробный список с обозначением -. Третий вызов sed является исходным, который обрабатывает обычные словари, теперь с добавлением обработки списков с - и отступами. Часть awk вводит индекс для каждого уровня отступа и увеличивает его, когда имя переменной пустое (т.е. при обработке списка). Текущее значение счетчиков используется вместо пустого vname. При подъеме на один уровень счетчики обнуляются.

Изменение: я создал хранилище GitHub для этого.

Ответ 10

Другой вариант - преобразовать YAML в JSON, а затем использовать jq для взаимодействия с представлением JSON либо для извлечения из него информации, либо для ее редактирования.

Я написал простой bash script, который содержит этот клей - см. проект Y2J на GitHub

Ответ 11

perl -ne 'chomp; printf qq/%s="%s"\n/, split(/\s*:\s*/,$_,2)' file.yml > file.sh

Ответ 12

Я нашел этот Jshon tool лучшим для этой цели, но в мире JSON.

Но я не нашел никаких следов в Интернете такого инструмента для YAML. Вы должны (по крайней мере, на данный момент) использовать Perl/Python/Ruby script для этого (как в предыдущих ответах).

Ответ 13

Если вам нужно одно значение, вы можете использовать инструмент, который преобразует ваш YAML-документ в JSON и jq в jq, например, yq.

Содержание sample.yaml:

---
bob:
  item1:
    cats: bananas
  item2:
    cats: apples
  thing:
    cats: oranges

Пример:

$ yq -r '.bob["thing"]["cats"]' sample.yaml 
oranges

Ответ 14

Я знаю, что это очень специфично, но я думаю, что мой ответ может быть полезен для определенных пользователей.
Если на вашем компьютере установлены node и npm, вы можете использовать js-yaml.
Сначала установите:

npm i -g js-yaml
# or locally
npm i js-yaml

то в вашем сценарии bash

#!/bin/bash
js-yaml your-yaml-file.yml

Также, если вы используете jq вы можете сделать что-то подобное

#!/bin/bash
json="$(js-yaml your-yaml-file.yml)"
aproperty="$(jq '.apropery' <<< "$json")"
echo "$aproperty"

Поскольку js-yaml преобразует файл yaml в литерал json string. Затем вы можете использовать строку с любым парсером json в вашей системе unix.

Ответ 15

Если у вас есть python 2 и PyYAML, вы можете использовать этот парсер, который я написал, называемый parse_yaml.py. Некоторые из более аккуратных вещей, которые он делает, позволяют вам выбрать префикс (в случае, если у вас есть более одного файла с похожими переменными) и выбрать одно значение из файла yaml.

Например, если у вас есть эти файлы yaml:

staging.yaml:

db:
    type: sqllite
    host: 127.0.0.1
    user: dev
    password: password123

prod.yaml:

db:
    type: postgres
    host: 10.0.50.100
    user: postgres
    password: password123

Вы можете загрузить оба без конфликтов.

$ eval $(python parse_yaml.py prod.yaml --prefix prod --cap)
$ eval $(python parse_yaml.py staging.yaml --prefix stg --cap)
$ echo $PROD_DB_HOST
10.0.50.100
$ echo $STG_DB_HOST
127.0.0.1

И даже вишня выбирает нужные вам ценности.

$ prod_user=$(python parse_yaml.py prod.yaml --get db_user)
$ prod_port=$(python parse_yaml.py prod.yaml --get db_port --default 5432)
$ echo prod_user
postgres
$ echo prod_port
5432

Ответ 16

Вы можете использовать эквивалент yq, который написан в golang:

./go-yg -yamlFile /home/user/dev/ansible-firefox/defaults/main.yml -key
firefox_version

возвращает:

62.0.3

Ответ 17

Вы также можете использовать Grunt (Running JavaScript Task Runner). Может быть легко интегрирована с оболочкой. Он поддерживает чтение файлов YAML (grunt.file.readYAML) и JSON (grunt.file.readJSON).

Это может быть достигнуто путем создания задачи в Gruntfile.js (или Gruntfile.coffee), например:

module.exports = function (grunt) {

    grunt.registerTask('foo', ['load_yml']);

    grunt.registerTask('load_yml', function () {
        var data = grunt.file.readYAML('foo.yml');
        Object.keys(data).forEach(function (g) {
          // ... switch (g) { case 'my_key':
        });
    });

};

то из оболочки просто запустите grunt foo (отметьте grunt --help для доступных задач).

Кроме того, вы можете реализовать задачи exec:foo (grunt-exec) с входными переменными, переданными из вашей задачи (foo: { cmd: 'echo bar <%= foo %>' }), чтобы распечатать вывод в любом формате, а затем передать его в другую команду.


Существует также аналогичный инструмент для Grunt, он называется gulp с дополнительным плагином gulp-yaml.

Установить через: npm install --save-dev gulp-yaml

Использование образца:

var yaml = require('gulp-yaml');

gulp.src('./src/*.yml')
  .pipe(yaml())
  .pipe(gulp.dest('./dist/'))

gulp.src('./src/*.yml')
  .pipe(yaml({ space: 2 }))
  .pipe(gulp.dest('./dist/'))

gulp.src('./src/*.yml')
  .pipe(yaml({ safe: true }))
  .pipe(gulp.dest('./dist/'))

Чтобы узнать больше о формате YAML, отметьте сайт YAML для доступных проектов, библиотек и других ресурсов, которые могут помочь вам разобрать этот формат.


Другие инструменты:

  • Jshon

    анализирует, считывает и создает JSON

Ответ 18

yaml.sh - это синтаксический анализатор bash yaml, похожий на ответы awk и sed, но завернутый с приятным api, который вы можете использовать непосредственно в своем скрипте.