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?

Hugo
fuente

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".

paxdiablo
fuente
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
DVK
fuente
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
10

Bash -ge 4 tiene el archivo de mapas incorporado para leer líneas de la entrada estándar en una variable de matriz.

help mapfile 

mapfile < file.txt lines
printf "%s" "${lines[@]}"

mapfile -t < file.txt lines    # strip trailing newlines
printf "%s\n" "${lines[@]}" 

Ver también:

http://bash-hackers.org/wiki/doku.php/commands/builtin/mapfile

Todd
fuente
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
DerWilts
fuente
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
Kenorb
fuente
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

Chris Johnson
fuente