Archivar contenido en variable unix con líneas nuevas


117

Tengo un archivo de texto test.txt con el siguiente contenido:

text1
text2 

Y quiero asignar el contenido del archivo a una variable UNIX, pero cuando hago esto:

testvar=$(cat test.txt)
echo $testvar

el resultado es:

text1 text2

en vez de

text1
text2 

¿Alguien puede sugerirme una solución para esto?

Respuestas:


184

La asignación no elimina los caracteres de nueva línea, en realidad es el echohacer esto. Simplemente necesita poner comillas alrededor de la cadena para mantener esas nuevas líneas:

echo "$testvar"

Esto le dará el resultado que desea. Vea la siguiente transcripción para una demostración:

pax> cat num1.txt ; x=$(cat num1.txt)
line 1
line 2

pax> echo $x ; echo '===' ; echo "$x"
line 1 line 2
===
line 1
line 2

La razón por la que las nuevas líneas se reemplazan con espacios no tiene que ver exclusivamente con el echocomando, sino que es una combinación de cosas.

Cuando se le da una línea de comando, la bashdivide en palabras de acuerdo con la documentación de la IFSvariable:

IFS: Separador de campo interno que se utiliza para dividir palabras después de la expansión ... el valor predeterminado es <space><tab><newline>.

Eso especifica que, de forma predeterminada, cualquiera de esos tres caracteres se puede usar para dividir su comando en palabras individuales. Después de eso, los separadores de palabras desaparecen, todo lo que queda es una lista de palabras.

Combine eso con la echodocumentación (un bashcomando interno), y verá por qué se generan los espacios:

echo [-neE] [arg ...]: Muestra los argumentos , separados por espacios, seguidos de una nueva línea.

Cuando lo usa echo "$x", obliga a toda la xvariable a ser una sola palabra de acuerdo con bash, por lo tanto, no se divide. Puedes ver eso con:

pax> function count {
...>    echo $#
...> }
pax> count 1 2 3
3
pax> count a b c d
4
pax> count $x
4
pax> count "$x"
1

Aquí, la countfunción simplemente imprime el número de argumentos dados. Las variantes 1 2 3y lo a b c dmuestran en acción.

Luego lo probamos con las dos variaciones de la xvariable. El uno sin citas muestra que hay cuatro palabras, "test", "1", "test"y "2". Agregar las comillas lo convierte en una sola palabra "test 1\ntest 2".


Las citas ... ¡eso es lo que me faltaba! ¡Gracias!
anonimita

También digno de mención: Arrastrando los saltos de línea será eliminado por el operador de la sustitución de comandos en sí: Pruébelo en línea!
Jonás

11

Esto se debe a la variable IFS (Separador de campo interno) que contiene una nueva línea.

$ cat xx1
1
2

$ A=`cat xx1`
$ echo $A
1 2

$ echo "|$IFS|"
|       
|

Una solución alternativa es restablecer IFS para que no contenga la nueva línea, temporalmente :

$ IFSBAK=$IFS
$ IFS=" "
$ A=`cat xx1` # Can use $() as well
$ echo $A
1
2
$ IFS=$IFSBAK

Para REVERTIR este cambio horrible para IFS:

IFS=$IFSBAK

Hice este cambio, pero ahora mis otras cosas no funcionan, por favor dígame que lo restablezca.
Pooja25

Si no lo necesita para ir a una variable, una línea directa:echo "$(IFS=''; cat text.txt)"
Curtis Yallop


3

Solo si alguien está interesado en otra opción:

content=( $(cat test.txt) )

a=0
while [ $a -le ${#content[@]} ]
do
        echo ${content[$a]}
        a=$[a+1]
done

3

Su variable está configurada correctamente por testvar=$(cat test.txt). Para mostrar esta variable que consta de caracteres de nueva línea, simplemente agregue comillas dobles, p. Ej.

echo "$testvar" 

Aquí está el ejemplo completo:

$ printf "test1\ntest2" > test.txt
$ testvar=$(<test.txt)
$ grep testvar <(set)
testvar=$'test1\ntest2'
$ echo "$testvar"
text1
text2
$ printf "%b" "$testvar"
text1
text2

0

La envdirutilidad proporciona una forma sencilla de hacer esto. envdirusa archivos para representar variables de entorno, con nombres de archivo mapeados a nombres de var env y mapeo de contenido de archivos a valores var env. Si el contenido del archivo contiene nuevas líneas, también lo hará la var env.

Ver https://pypi.python.org/pypi/envdir

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.