Quiero escribir algunos textos predefinidos en un archivo con lo siguiente:
text="this is line one\n
this is line two\n
this is line three"
echo -e $text > filename
Estoy esperando algo como esto:
this is line one
this is line two
this is line three
Pero conseguí esto:
this is line one
this is line two
this is line three
Estoy seguro de que no hay espacio después de cada \n
, pero ¿cómo sale el espacio extra?
Heredoc suena más conveniente para este propósito. Se utiliza para enviar varios comandos a un programa de intérprete de comandos como ex o cat
cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage
La cadena después de <<
indica dónde detenerse.
Para enviar estas líneas a un archivo, usa:
cat > $FILE <<- EOM
Line 1.
Line 2.
EOM
También puedes almacenar estas líneas en una variable:
read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM
Esto almacena las líneas a la variable llamada VAR
.
Al imprimir, recuerde las citas alrededor de la variable, de lo contrario no verá los caracteres de nueva línea.
echo "$VAR"
Aún mejor, puedes usar la sangría para que se destaque más en tu código. Esta vez solo agregue un -
después de <<
para detener la aparición de las pestañas.
read -r -d '' VAR <<- EOM
This is line 1.
This is line 2.
Line 3.
EOM
Pero luego debe usar tabulaciones, no espacios, para la sangría en su código.
Si estás tratando de convertir la cadena en una variable, otra forma fácil es algo como esto:
USAGE=$(cat <<-END
This is line one.
This is line two.
This is line three.
END
)
Si sangra su cadena con pestañas (es decir, '\ t'), la sangría se eliminará. Si hace sangría con espacios, la sangría quedará en.
NOTA: Es es significativo que el último paréntesis de cierre está en otra línea. El texto END
debe aparecer en una línea por sí mismo.
echo
agrega espacios entre los argumentos pasados. $text
está sujeto a expansión de variables y división de palabras, por lo que su comando echo
es equivalente a
echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n" ...
Puede ver que se agregará un espacio antes de "esto". Puede eliminar los caracteres de nueva línea y citar $text
para conservar las nuevas líneas:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
O puede usar printf
, que es más robusto y portátil que echo
:
printf "%s\n" "this is line one" "this is line two" "this is line three" > filename
En bash
, que admite la expansión de llaves, incluso podría hacer:
printf "%s\n" "this is line "{one,two,three} > filename
en un script de bash los siguientes trabajos:
#!/bin/sh
text="this is line one\nthis is line two\nthis is line three"
echo $text > filename
alternativamente:
text="this is line one
this is line two
this is line three"
echo "$text" > filename
cat nombre de archivo da:
this is line one
this is line two
this is line three
He encontrado más soluciones ya que quería tener cada línea correctamente sangrada:
Puedes usar echo
:
echo "this is line one" \
"\n""this is line two" \
"\n""this is line three" \
> filename
No funciona si pones "\n"
justo antes de \
en el final de una línea.
Alternativamente, puedes usar printf
para una mejor portabilidad (se me ocurrió que tuve muchos problemas con echo
):
printf '%s\n' \
"this is line one" \
"this is line two" \
"this is line three" \
> filename
Otra solución podría ser:
text=''
text="${text}this is line one\n"
text="${text}this is line two\n"
text="${text}this is line three\n"
printf "%b" "$text" > filename
o
text=''
text+="this is line one\n"
text+="this is line two\n"
text+="this is line three\n"
printf "%b" "$text" > filename
Otra solución se logra mezclando printf
y sed
.
if something
then
printf '%s' '
this is line one
this is line two
this is line three
' | sed '1d;$d;s/^ //g'
fi
No es fácil refactorizar el código con este formato, ya que codifica el nivel de sangrado en el código.
Es posible usar una función auxiliar y algunos trucos de sustitución de variables:
unset text
_() { text="${text}${text+
}${*}"; }
# That's an empty line which demonstrates the reasoning behind
# the usage of "+" instead of ":+" in the variable substitution
# above.
_ ""
_ "this is line one"
_ "this is line two"
_ "this is line three"
unset -f _
printf '%s' "$text"
La siguiente es mi forma preferida de asignar una cadena multilínea a una variable (creo que se ve bien).
read -r -d '' my_variable << \
_______________________________________________________________________________
String1
String2
String3
...
StringN
_______________________________________________________________________________
El número de guiones bajos es el mismo (aquí 80) en ambos casos.
funcionará si lo pones de la siguiente manera:
AA='first line
\nsecond line
\nthird line'
echo $AA
output:
first line
second line
third line