Deseo proporcionar un archivo de configuración estructurado que sea lo más fácil posible para que lo edite un usuario no técnico (desafortunadamente tiene que ser un archivo) y por eso quería usar YAML. Sin embargo, no puedo encontrar ninguna manera de analizar esto desde un script de shell de Unix.
192
yq
para leer / escribir archivos yaml en shell. La página del proyecto está aquí: mikefarah.github.io/yq Puede instalar la herramienta conbrew
,apt
o descargar el binario. Leer un valor es tan simple comoyq r some.yaml key.value
Respuestas:
Mi caso de uso puede o no ser el mismo que el que estaba preguntando esta publicación original, pero definitivamente es similar.
Necesito obtener algunos YAML como variables bash. El YAML nunca tendrá más de un nivel de profundidad.
YAML se ve así:
Salida like-a dis:
Logré el resultado con esta línea:
s/:[^:\/\/]/="/g
lo encuentra:
y lo reemplaza por="
, mientras lo ignora://
(para URL)s/$/"/g
se agrega"
al final de cada líneas/ *=/=/g
elimina todos los espacios antes=
fuente
{KEY: 'value', ...}
; y posiblemente otros. Lo más importante, si tiene la intención de evaluar el resultado como código shell, sería muy inseguro.Aquí hay un analizador de solo bash que aprovecha sed y awk para analizar archivos yaml simples:
Entiende archivos como:
Que, cuando se analiza usando:
dará salida:
también comprende archivos yaml, generados por ruby que pueden incluir símbolos ruby, como:
y generará lo mismo que en el ejemplo anterior.
El uso típico dentro de un script es:
parse_yaml acepta un argumento de prefijo para que todas las configuraciones importadas tengan un prefijo común (lo que reducirá el riesgo de colisiones en el espacio de nombres).
rendimientos:
Tenga en cuenta que las configuraciones anteriores en un archivo pueden ser referidas por configuraciones posteriores:
Otro buen uso es analizar primero un archivo predeterminado y luego la configuración del usuario, que funciona ya que esta última anula la primera:
fuente
-
notación yaml en matrices bash nativas también!global__debug
lugar deglobal_debug
.He escrito
shyaml
en Python para las necesidades de consulta de YAML desde la línea de comandos del shell.Visión general:
Archivo YAML de ejemplo (con características complejas):
Consulta básica:
Consulta de bucle más compleja sobre valores complejos:
Algunos puntos clave:
\0
La salida acolchada está disponible para la manipulación sólida de entradas multilínea.subvalue.maintainer
es una clave válida).subvalue.things.-1
es el último elemento de lasubvalue.things
secuencia).Hay más muestras y documentación disponibles en la página de Github de shyaml o en la página de PyPI de shyaml .
fuente
cat docker-compose.yml | shyaml get-value api.environment | grep -v null | awk -F': ' '{print $2 > ("envdir/" $1)}'
shyaml
es ridículamente lento( https://github.com/mikefarah/yq#readme )
Como ejemplo (robado directamente de la documentación ), dado un archivo sample.yaml de:
luego
saldrá
fuente
Es posible pasar un pequeño script a algunos intérpretes, como Python. Una manera fácil de hacerlo usando Ruby y su biblioteca YAML es la siguiente:
, donde
data
es un hash (o matriz) con los valores de yaml.Como beneficio adicional, analizará muy bien el frente de Jekyll .
fuente
RUBY_SCRIPT
variable es un script ruby que puede escribirse en un archivo en su lugar (ejecutarse conruby -ryaml <rubyscript_filename>
). Contiene la lógica para transformar el texto de entrada en texto de salida, almacenando internamente el contenido en ladata
variable. El eco genera un texto yaml, pero puede utilizarlocat <yaml_filename>
para canalizar el contenido de un archivo.stdout
que se alimente a la variable, no tienes que confiar en archivos temporales! usox=$(...)
o inclusoread a b c < <(...)
). Por lo tanto, esta es una solución válida cuando sabe exactamente lo que desea obtener en el archivo YAML y sabe cómo escribir las líneas rubí para acceder a estos datos. Incluso si es tosco, es una prueba completa del concepto de la idea en mi humilde opinión. Sin embargo, es cierto que no le proporciona una abstracción completa de bash.Dado que Python3 y PyYAML son dependencias bastante fáciles de cumplir hoy en día, lo siguiente puede ayudar:
fuente
yaml.safe_load
como es más seguro. pyyaml.org/wiki/PyYAMLDocumentationaquí una versión extendida de la respuesta de Stefan Farestam:
Esta versión admite la
-
notación y la notación corta para diccionarios y listas. La siguiente entrada:produce esta salida:
como puede ver, los
-
elementos se numeran automáticamente para obtener diferentes nombres de variables para cada elemento. Enbash
no hay matrices multidimensionales, por lo que esta es una forma de trabajo alrededor. Múltiples niveles son compatibles. Para evitar el problema de los espacios en blanco finales mencionados por @briceburg, se deben encerrar los valores entre comillas simples o dobles. Sin embargo, todavía hay algunas limitaciones: la expansión de los diccionarios y las listas puede producir resultados incorrectos cuando los valores contienen comas. Además, las estructuras más complejas, como los valores que abarcan varias líneas (como las teclas ssh) no son compatibles (todavía).Algunas palabras sobre el código: el primer
sed
comando expande la forma abreviada de los diccionarios{ key: value, ...}
a regular y los convierte a un estilo yaml más simple. La segundased
llamada hace lo mismo para la notación corta de listas y se convierte[ entry, ... ]
en una lista detallada con la-
notación. La tercerased
llamada es la original que maneja los diccionarios normales, ahora con la adición de manejar listas con-
sangrías. Laawk
parte introduce un índice para cada nivel de sangría y lo aumenta cuando el nombre de la variable está vacío (es decir, al procesar una lista). Se utiliza el valor actual de los contadores en lugar del nombre de v vacío. Al subir un nivel, los contadores se ponen a cero.Editar: he creado un repositorio github para esto.
fuente
Difícil de decir porque depende de lo que quiera que extraiga el analizador de su documento YAML. Para los casos simples, es posible que pueda utilizar
grep
,cut
,awk
etc. Para el análisis más complejo que tendría que utilizar un análisis en toda regla biblioteca de Python como PyYAML o YAML :: Perl .fuente
¡Acabo de escribir un analizador que llamé Yay! (¡ Yaml no es Yamlesque! ) Que analiza Yamlesque , un pequeño subconjunto de YAML. Entonces, si está buscando un analizador YAML 100% compatible para Bash, entonces este no lo es. Sin embargo, para citar el OP, si desea un archivo de configuración estructurado que sea lo más fácil posible para un usuario no técnico para editar que sea similar a YAML, esto puede ser de interés.
Está inspirado en la respuesta anterior, pero escribe matrices asociativas ( sí, requiere Bash 4.x ) en lugar de variables básicas. Lo hace de una manera que permite analizar los datos sin el conocimiento previo de las claves para que se pueda escribir el código controlado por datos.
Además de los elementos de la matriz de clave / valor, cada matriz tiene una
keys
matriz que contiene una lista de nombres de clave, unachildren
matriz que contiene nombres de matrices secundarias y unaparent
clave que se refiere a su padre.Este es un ejemplo de Yamlesque:
Aquí hay un ejemplo que muestra cómo usarlo:
que salidas:
Y aquí está el analizador:
Hay algo de documentación en el archivo fuente vinculado y a continuación hay una breve explicación de lo que hace el código.
La
yay_parse
función primero localiza elinput
archivo o sale con un estado de salida de 1. Luego, determina el conjunto de datosprefix
, ya sea explícitamente especificado o derivado del nombre del archivo.Escribe
bash
comandos válidos en su salida estándar que, si se ejecutan, definen matrices que representan el contenido del archivo de datos de entrada. El primero de ellos define la matriz de nivel superior:Tenga en cuenta que las declaraciones de matriz son asociativas (
-A
), que es una característica de Bash versión 4. Las declaraciones también son globales (-g
), por lo que pueden ejecutarse en una función pero estar disponibles para el alcance global como elyay
ayudante:Los datos de entrada se procesan inicialmente con
sed
. Descarta líneas que no coinciden con la especificación de formato Yamlesque antes de delimitar los campos válidos de Yamlesque con un carácter de separador de archivo ASCII y eliminar las comillas dobles que rodean el campo de valor.Las dos expresiones son similares; difieren solo porque el primero selecciona los valores entre comillas, mientras que el segundo selecciona los que no están entre comillas.
El separador de archivos (28 / hex 12 / octal 034) se utiliza porque, como carácter no imprimible, es poco probable que esté en los datos de entrada.
El resultado se canaliza en el
awk
que procesa su entrada una línea a la vez. Utiliza el FS caracteres para asignar cada campo a una variable:Todas las líneas tienen una sangría (posiblemente cero) y una clave, pero no todas tienen un valor. Calcula un nivel de sangría para la línea que divide la longitud del primer campo, que contiene el espacio en blanco inicial, por dos. Los elementos de nivel superior sin sangría están en el nivel de sangría cero.
A continuación, determina qué
prefix
usar para el elemento actual. Esto es lo que se agrega al nombre de una clave para crear un nombre de matriz. Hay unaroot_prefix
para la matriz de nivel superior que se define como el nombre de conjunto de datos y un carácter de subrayado:La
parent_key
es la clave en el nivel de sangría por encima del nivel de sangría de la línea actual y representa la colección de la que forma parte la línea actual. Los pares clave / valor de la colección se almacenarán en una matriz con su nombre definido como la concatenación deprefix
yparent_key
.Para el nivel superior (nivel de sangría cero), el prefijo del conjunto de datos se utiliza como clave principal, por lo que no tiene prefijo (está establecido en
""
). Todos los demás arreglos tienen el prefijo raíz.A continuación, la clave actual se inserta en una matriz (awk-internal) que contiene las claves. Esta matriz persiste durante toda la sesión awk y, por lo tanto, contiene claves insertadas por líneas anteriores. La clave se inserta en la matriz usando su sangría como índice de la matriz.
Debido a que esta matriz contiene claves de líneas anteriores, se eliminan todas las claves con un nivel de sangría mayor que el nivel de sangría de la línea actual:
Esto deja la matriz de claves que contiene el llavero desde la raíz en el nivel de sangría 0 a la línea actual. Elimina las claves obsoletas que permanecen cuando la línea anterior se sangra más profundo que la línea actual.
La sección final genera los
bash
comandos: una línea de entrada sin un valor inicia un nuevo nivel de sangría (una colección en lenguaje YAML) y una línea de entrada con un valor agrega una clave a la colección actual.El nombre de la colección es la concatenación de la línea actual
prefix
yparent_key
.Cuando una clave tiene un valor, una clave con ese valor se asigna a la colección actual de esta manera:
La primera instrucción genera el comando para asignar el valor a un elemento de matriz asociativo nombrado después de la clave y la segunda genera el comando para agregar la clave a la
keys
lista delimitada por espacios de la colección :Cuando una clave no tiene un valor, se inicia una nueva colección como esta:
La primera instrucción genera el comando para agregar la nueva colección a la
children
lista delimitada por espacios de la colección actual y la segunda genera el comando para declarar una nueva matriz asociativa para la nueva colección:Toda la salida de
yay_parse
puede ser analizada como comandos bash por los comandos basheval
osource
integrados.fuente
examples
yusr/lib
, Estos están vinculados en mi respuesta a la pregunta. Si hay interés, podría dividirlo en su propio repositorio.fuente
Otra opción es convertir el YAML a JSON, luego usar jq para interactuar con la representación JSON, ya sea para extraer información o editarla.
Escribí un script de bash simple que contiene este pegamento; vea el proyecto Y2J en GitHub
fuente
Si necesita un valor único, podría utilizar una herramienta que convierta su documento YAML a JSON y lo alimente
jq
, por ejemployq
.Contenido de sample.yaml:
Ejemplo:
fuente
Sé que esto es muy específico, pero creo que mi respuesta podría ser útil para ciertos usuarios.
Si tiene
node
enpm
instaló en su máquina, puede usarjs-yaml
.Primera instalación:
entonces en tu script bash
Además, si estás usando
jq
puedes hacer algo asíPorque
js-yaml
convierte un archivo yaml en un literal de cadena json. Luego puede usar la cadena con cualquier analizador json en su sistema unix.fuente
Si tiene Python 2 y PyYAML, puede usar este analizador que escribí llamado parse_yaml.py . Algunas de las cosas más ingeniosas que hace es permitirle elegir un prefijo (en caso de que tenga más de un archivo con variables similares) y elegir un solo valor de un archivo yaml.
Por ejemplo, si tiene estos archivos yaml:
staging.yaml:
prod.yaml:
Puede cargar ambos sin conflicto.
E incluso elige los valores que quieras.
fuente
Podrías usar un equivalente de yq que está escrito en golang:
devoluciones:
fuente
También puede considerar usar Grunt (The JavaScript Task Runner). Se puede integrar fácilmente con la carcasa. Admite la lectura de archivos YAML (
grunt.file.readYAML
) y JSON (grunt.file.readJSON
).Esto se puede lograr creando una tarea en
Gruntfile.js
(oGruntfile.coffee
), por ejemplo:luego desde shell simplemente ejecute
grunt foo
(verifiquegrunt --help
las tareas disponibles)Además, puede implementar
exec:foo
tareas (grunt-exec
) con variables de entrada pasadas desde su tarea (foo: { cmd: 'echo bar <%= foo %>' }
) para imprimir la salida en el formato que desee y luego canalizarla a otro comando.También hay una herramienta similar a Grunt, se llama gulp con el complemento adicional gulp-yaml .
Instalar a través de:
npm install --save-dev gulp-yaml
Uso de la muestra:
Para obtener más opciones para lidiar con el formato YAML , consulte el sitio de YAML para ver los proyectos, bibliotecas y otros recursos disponibles que pueden ayudarlo a analizar ese formato.
Otras herramientas:
Jshon
fuente
Sé que mi respuesta es específica, pero si uno ya tiene PHP y Symfony instalados, puede ser muy útil usar el analizador YAML de Symfony.
Por ejemplo:
Aquí simplemente solía
var_dump
generar la matriz analizada pero, por supuesto, puedes hacer mucho más ... :)fuente