Cadenas multilínea en YAML: cuándo usar | y cuándo usar >
Un valor multilínea en YAML tiene dos símbolos de bloque, una barra vertical y un signo mayor que, y además tres estilos escalares —plano, con comillas simples y con comillas dobles— que también abarcan varias líneas. Cada uno conserva o pliega tus saltos de forma distinta, y elegir mal convierte un script en una sola línea rota. Aquí está el cuadro completo, con las trampas.
Quieres un valor multilínea en YAML. Quizá un script de shell, una descripción larga, un bloque de SQL. YAML te da dos símbolos: | y >. Elige el equivocado y no salta ningún error. El valor sale mal, sin más. Un script con > se aplasta en una línea y deja de correr. Una descripción con | conserva cada salto que pusiste solo para que cupiera en la pantalla.
A los dos se los suele llamar «literal» y «plegado». El nombre es correcto, pero no sirve en el momento de elegir. La pregunta que de verdad lo decide es esta: ¿los saltos de este texto significan algo?
Si significan algo, consérvalos. Usa |. Los saltos de un script separan comandos. Los de una tabla separan filas. Si no significan nada —partiste una frase larga para que cupiera en el editor—, déjalos ir. Usa >.
Con eso resuelves casi todo. Pero los escalares de bloque tienen más rincones, y algunos muerden. Este artículo los recorre todos: los dos símbolos, el salto final, la trampa de la indentación, y el hecho de que los escalares de bloque ni siquiera son la única forma de escribir una cadena multilínea.
| conserva los saltos; > los pliega en espacios
La misma entrada, dos símbolos, dos cadenas distintas. Con |:
message: |
line one
line two
obtienes "line one\nline two\n". El salto se queda. Con >:
message: >
line one
line two
obtienes "line one line two\n". El salto se volvió un espacio, como si hubieras escrito una sola línea larga.
Ese espacio es el sentido de >. Es para la prosa. Envuelves una descripción larga en el archivo para que se lea bien, pero debe llegar como una línea. Donde los saltos son estructura, es justo lo incorrecto. Míralo arruinar un script:
script: >
set -e
echo hi
echo bye
Se pliega a "set -e echo hi echo bye\n". Tres comandos en una línea. El mismo bloque con | da "set -e\necho hi\necho bye\n", que es lo que querías. Ante la duda, usa |. Conservar saltos que no necesitas suele ser inocuo; perder los que necesitas es un error.
Lo que > no pliega: la indentación extra y las líneas en blanco
El plegado tiene una excepción, y conviene conocerla. Una línea indentada más que el resto del bloque no se pliega. Conserva sus propios saltos, tal cual. Mira:
note: >
prose that wraps
onto two lines
indented line, kept as-is
back to prose
Eso da "prose that wraps onto two lines\n indented line, kept as-is\nback to prose\n". La prosa envuelta se plegó a espacios. La línea más indentada conservó sus saltos y su indentación. Así que un bloque plegado puede guardar una «isla literal»: puedes envolver una descripción y aun así incrustar un fragmento de código.
También es una trampa. Un espacio de más, sin querer, vuelve literal esa línea. En la salida aparece un salto que no querías, y nada te avisa.
Las líneas en blanco son lo otro que > deja intacto. Una línea en blanco dentro de un bloque plegado no se aplasta. Se vuelve un salto. Así que > todavía separa párrafos, aunque pliegue los saltos dentro de cada uno:
text: >
first paragraph
second paragraph
Eso da "first paragraph\nsecond paragraph\n". Un salto dentro de un párrafo se plegaría a un espacio. La línea en blanco entre párrafos se queda como un salto.
Chomping: cuántos saltos finales
Elegido | o >, al final del bloque queda algo pequeño. Qué pasa con el salto tras la última línea. YAML lo llama «chomping». Tiene tres modos.
- Por defecto, «clip»: exactamente un salto final, dejes las líneas en blanco que dejes.
|da"text\n". - Recortar,
-: ningún salto final.|-da"text". - Conservar,
+: todos los saltos finales que escribiste.|+sobre un bloque con dos líneas en blanco después da"text\n\n\n".
Casi siempre el valor por defecto está bien y ni lo piensas. Importa en dos casos. Cuando un salto final rompe algo —un valor que vas a hashear, un token, un nombre de archivo—, usa -, como en key: |-. Cuando las líneas en blanco finales tienen sentido y deben sobrevivir, usa +. En lo demás, no lo toques.
Cuando el texto empieza con espacios
Aquí hay una sutil. YAML decide la indentación del bloque a partir de su primera línea no vacía. Normalmente es lo que quieres. Pero a veces tu contenido empieza con espacios que son reales: un fragmento ya indentado, por ejemplo. YAML lee esos espacios iniciales como la indentación propia del bloque y los quita. Peor aún: si una línea posterior está menos indentada, el bloque termina antes y obtienes un error de análisis.
El remedio es el indicador de indentación: un dígito justo después de | o >. Declara la indentación en vez de adivinarla.
code: |2
leading spaces kept
less-indented line
Ese 2 significa dos espacios de indentación relativos al padre, no una columna absoluta. Aquí la clave está en la columna cero, así que el contenido empieza en la columna dos. Anida la misma clave un nivel más y |2 significaría dos espacios más allá de ese nivel. Así que leading spaces kept conserva cuatro espacios, y less-indented line conserva dos. El dígito se combina con el chomping en cualquier orden: |2- y |-2 significan lo mismo.
Los escalares de bloque no son la única vía
Puedes escribir una cadena multilínea sin ningún símbolo. Los escalares plano, con comillas simples y con comillas dobles también abarcan varias líneas. Los tres siguen las reglas de plegado de YAML: un salto normal entre dos líneas se convierte en un espacio, pero una línea en blanco conserva el salto. La regla que conserva las líneas más indentadas es propia de >; aquí no aplica.
plain: first line
second line
single: 'first line
second line'
double: "first line
second line"
Los tres dan "first line second line". Los tres pliegan igual: un salto normal entre dos líneas se vuelve un espacio, pero una línea en blanco sigue siendo un salto. La diferencia principal está en los escapes, las comillas y las restricciones sintácticas de los escalares planos.
Las comillas dobles interpretan escapes. "a\nb" son dos líneas. "tab\there" lleva un tabulador real. Una barra invertida al final de línea une la siguiente sin espacio. Las comillas simples no interpretan nada. 'a\nb' es una barra invertida literal y una n. Para meter una comilla dentro de comillas simples, la duplicas: 'it''s here' es it's here. Los escalares de bloque (|, >) no interpretan escapes en absoluto: un \n dentro es una barra invertida y una n.
Los cinco, uno al lado del otro:
| Estilo | Saltos de línea | Escapes \n | Salto final |
|---|---|---|---|
| literal | conserva | no | uno, ajustable con - / + |
> plegado | pliega a espacios (línea en blanco = salto; líneas más indentadas se conservan) | no | uno, ajustable con - / + |
"dobles" | saltos normales a espacios; línea en blanco = salto | sí | ninguno |
'simples' | saltos normales a espacios; línea en blanco = salto | no ('' = una comilla) | ninguno |
| plano | saltos normales a espacios; línea en blanco = salto | no | ninguno |
De la tabla salen dos ideas. Si quieres saltos reales, solo | los da sin escapes. Si quieres escapes como \n o \t, solo las comillas dobles los leen.
Todo fin de línea se vuelve \n
Otra normalización, fácil de olvidar. YAML reescribe cada salto de un escalar a \n. Un archivo guardado en Windows con finales CRLF aun así se analiza a \n, no a \r\n. No puedes colar un retorno de carro por la fuente. Si de verdad lo necesitas, escápalo en una cadena con comillas dobles: "line\r\n".
Dónde muerde en proyectos reales
La misma regla reaparece. Si el valor es en sí un archivo o un script, quiere |.
- Un ConfigMap de Kubernetes incrusta un archivo de configuración entero como un valor. Ese valor es casi siempre
|. Los saltos son el archivo. - GitHub Actions escribe los pasos de shell como
run: |. Cada línea es un comando, así que los saltos deben quedarse. - Docker Compose y Ansible hacen lo mismo con scripts y archivos en línea.
> aparece en el trabajo opuesto: texto para humanos. Un campo description: largo. Un comentario que envolviste por ancho. Si el valor es prosa, plégalo. Si es un archivo, consérvalo.
La decisión, en breve
- ¿Los saltos significan algo? Sí →
|. No, solo envuelven →>. - ¿No estás seguro? Usa
|. Conservar saltos es seguro; perderlos es un error. - Cuando los saltos son parte del contenido —código, scripts, tablas, archivos incrustados— usa
|. - ¿Necesitas escapes
\no\t? Comillas dobles. ¿Saltos literales?|. - El salto final lo fija el chomping: por defecto uno
\n,-ninguno,+todos. - ¿El contenido empieza con espacios? Usa el indicador de indentación, como
|2.
Mira la cadena real
Nada de esto se ve leyendo el YAML. Un \n y un espacio se ven iguales en la página. Así que compruébalo. Pega el archivo en el conversor de YAML y lee la salida JSON. Cada salto aparece como un \n explícito, cada plegado como un espacio, cada salto final tal como es. Ves la cadena que recibe tu programa, no la forma de la fuente.
Esto forma parte del grupo sobre formatos de configuración, junto al pilar sobre elegir entre JSON, YAML y TOML y a ¿por qué se rompe mi YAML? sobre las formas ruidosas y silenciosas en que YAML falla. Los escalares de bloque son un lugar más donde YAML hace algo razonable que no es lo que suponías. La solución, como siempre, es mirar el valor real en vez de fiarte de la forma de la fuente.