Intentando insertar nueva línea en una variable en bash

yo tengo

var="abc" for i in $var do p=`echo -e $p'\n'$i` done echo $p 

Quiero el último eco para imprimir

 a b c 

Tenga en cuenta que quiero que la variable p contenga nuevas líneas. ¿Cómo puedo hacer eso?

Resumen

  1. Insertar \n

     p="${var1}\n${var2}" echo -e "${p}" 
  2. Insertar una nueva línea en el código fuente

     p="${var1} ${var2}" echo "${p}" 
  3. Usando $'\n' (solo bash y zsh )

     p="${var1}"$'\n'"${var2}" echo "${p}" 

Detalles

1. Insertar \n

 p="${var1}\n${var2}" echo -e "${p}" 

echo -e interpreta los dos caracteres "\n" como una nueva línea.

 var="abc" first_loop=true for i in $var do p="$p\n$i" # Append unset first_loop done echo -e "$p" # Use -e 

Evite la nueva línea adicional

 var="abc" first_loop=1 for i in $var do (( $first_loop )) && # "((...))" is bash specific p="$i" || # First -> Set p="$p\n$i" # After -> Append unset first_loop done echo -e "$p" # Use -e 

Usando una función

 embed_newline() { local p="$1" shift for i in "$@" do p="$p\n$i" # Append done echo -e "$p" # Use -e } var="abc" p=$( embed_newline $var ) # Do not use double quotes "$var" echo "$p" 

2. Insertar una nueva línea en el código fuente

 var="abc" for i in $var do p="$p $i" # New line directly in the source code done echo "$p" # Double quotes required # But -e not required 

Evite la nueva línea adicional

 var="abc" first_loop=1 for i in $var do (( $first_loop )) && # "((...))" is bash specific p="$i" || # First -> Set p="$p $i" # After -> Append unset first_loop done echo "$p" # No need -e 

Usando una función

 embed_newline() { local p="$1" shift for i in "$@" do p="$p $i" # Append done echo "$p" # No need -e } var="abc" p=$( embed_newline $var ) # Do not use double quotes "$var" echo "$p" 

3. Usando $'\n' (menos portátil)

bash y zsh interpreta $'\n' como una nueva línea.

 var="abc" for i in $var do p="$p"$'\n'"$i" done echo "$p" # Double quotes required # But -e not required 

Evite la nueva línea adicional

 var="abc" first_loop=1 for i in $var do (( $first_loop )) && # "((...))" is bash specific p="$i" || # First -> Set p="$p"$'\n'"$i" # After -> Append unset first_loop done echo "$p" # No need -e 

Usando una función

 embed_newline() { local p="$1" shift for i in "$@" do p="$p"$'\n'"$i" # Append done echo "$p" # No need -e } var="abc" p=$( embed_newline $var ) # Do not use double quotes "$var" echo "$p" 

La salida es igual para todos

 a b c 

Un agradecimiento especial a los contribuyentes de esta respuesta: kevinf , Gordon Davisson , l0b0 , Dolda2000 y tripleee .


EDITAR

  • Ver también la respuesta de BinaryZebra brindando muchos detalles.
  • La respuesta de Abhijeet Rastogi y la respuesta de Dimitry explican cómo evitar el bucle for en los fragmentos bash .

La solución trivial es poner esas nuevas líneas donde las desee.

 var="a b c" 

Sí, es una tarea envuelta en varias líneas.

Sin embargo, tendrá que citar dos veces el valor al interpolarlo, de lo contrario, el shell lo dividirá en espacios en blanco, convirtiendo efectivamente cada línea nueva en un espacio único (y también expandirá cualquier comodín).

 echo "$p" 

En general, debe hacer una cita doble de todas las interpolaciones variables a menos que desee específicamente el comportamiento descrito anteriormente.

Pruebe echo $'a\nb' .

Si desea almacenarlo en una variable y luego usarlo con las líneas nuevas intactas, tendrá que citar su uso correctamente:

 var=$'a\nb\nc' echo "$var" 

O bien, para arreglar su progtwig de ejemplo literalmente:

 var="abc" for i in $var; do p="`echo -e "$p\\n$i"`" done echo "$p" 

Hay tres niveles en los que se puede insertar una nueva línea en una variable.
Bueno … técnicamente cuatro, pero las dos primeras son solo dos formas de escribir la nueva línea en el código.

1.1. En la creación.

Lo más básico es crear la variable con las nuevas líneas ya.
Escribimos el valor de la variable en el código con las nuevas líneas ya insertadas.

 $ var="a > b > c" $ echo "$var" a b c 

O, dentro de un código de script:

 var="a b c" 

Sí, eso significa escribir Enter donde sea necesario en el código.

1.2. Crear usando cotizaciones de shell

La secuencia $ ' es una expansión de shell especial en bash y zsh.

 var=$'a\nb\nc' 

La línea es analizada por el shell y expandida a «var =» a newline b newline c »», que es exactamente lo que queremos que sea la variable var.
Eso no funcionará en los proyectiles más antiguos.

2. Usar expansiones de caparazón.

Básicamente es una expansión de comandos con varios comandos:

  1. echo -e

     var="$( echo -e "a\nb\nc" )" 
  2. El printf de bash y zsh ‘% b’

     var="$( printf '%b' "a\nb\nc" )" 
  3. El bash printf -v

     printf -v var '%b' "a\nb\nc" 
  4. Printf simple simple (funciona en la mayoría de las conchas):

     var="$( printf 'a\nb\nc' )" 

3. Usando la ejecución del shell.

Todos los comandos enumerados en la segunda opción se podrían usar para expandir el valor de una var, si esa var contiene caracteres especiales.
Entonces, todo lo que necesitamos hacer es obtener esos valores dentro de var y ejecutar algún comando para mostrar:

 var="a\nb\nc" # var will contain the characters \n not a newline. echo -e "$var" # use echo. printf "%b" "$var" # use bash %b in printf. printf "$var" # use plain printf. 

Tenga en cuenta que printf es algo inseguro si el valor var es controlado por un atacante.

no hay necesidad de usar para el ciclo

puede beneficiarse de las funciones de expansión de parámetros bash:

 var="abc"; var=${var// /\\n}; echo -e $var a b c 

o simplemente usa tr:

 var="abc" echo $var | tr " " "\n" a b c 

solución sed

 echo "abc" | sed 's/ \+/\n/g' 

Resultado:

 a b c 
 var="abc" for i in $var do p=`echo -e "$p"'\n'$i` done echo "$p" 

La solución fue simplemente proteger la nueva línea insertada con un “” durante la iteración actual cuando ocurre la sustitución de la variable.