Quiero leer un archivo y guardarlo en variable, pero necesito mantener la variable y no solo imprimir el archivo. ¿Cómo puedo hacer esto? He escrito este script pero no es exactamente lo que necesitaba:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
En mi script, puedo dar el nombre del archivo como parámetro, por lo tanto, si el archivo contiene "aaaa", por ejemplo, imprimirá esto:
aaaa
11111-----
Pero esto solo imprime el archivo en la pantalla, ¡y quiero guardarlo en una variable! ¿Hay una forma fácil de hacer esto?
cat
o$(<someFile)
dará como resultado una salida incompleta (el tamaño es menor que el archivo real).Respuestas:
En multiplataforma, el mínimo común denominador
sh
utiliza:En
bash
ozsh
, para leer un archivo completo en una variable sin invocarcat
:Invocando
cat
enbash
ozsh
sorber un archivo sería considerado un uso inútil de gato .Tenga en cuenta que no es necesario citar la sustitución del comando para preservar las nuevas líneas.
Ver: Bash Hacker's Wiki - Sustitución de comandos - Especialidades .
fuente
value="`cat config.txt`"
yvalue="$(<config.txt)"
sería más seguro en caso de que config.txt contenga espacios?cat
como anteriormente no siempre se considera un uso inútil decat
. Por ejemplo,< invalid-file 2>/dev/null
dará como resultado un mensaje de error al que no se puede enrutar/dev/null
, mientrascat invalid-file 2>/dev/null
que se enruta correctamente/dev/null
.value=$(<config.txt)
es bueno, perovalue = $(<config.txt)
es malo. Cuidado con esos espacios.Si desea leer todo el archivo en una variable:
Si quieres leerlo línea por línea:
fuente
echo "$value"
. De lo contrario, el shell realizará la tokenización de espacios en blanco y la expansión de comodines en el valor.read -r
lugar de soloread
, siempre, a menos que requiera específicamente el extraño comportamiento heredado al que se refiere.Dos trampas importantes
que fueron ignoradas por otras respuestas hasta ahora:
Eliminación de línea nueva posterior a la expansión del comando
Este es un problema para:
soluciones de tipo, pero no para
read
soluciones basadas.La expansión de comandos elimina las nuevas líneas finales:
Salidas:
Esto rompe el método ingenuo de lectura de archivos:
Solución alternativa de POSIX: agregue un carácter adicional a la expansión del comando y elimínelo más tarde:
Salidas:
Solución alternativa casi POSIX: codificación ASCII. Vea abajo.
Eliminación de caracteres NUL
No hay una forma sensata de Bash de almacenar caracteres NUL en variables .
Esto afecta tanto a la expansión como a las
read
soluciones, y no conozco una buena solución para ello.Ejemplo:
Salidas:
Ja, nuestro NUL se ha ido!
Soluciones alternativas:
Codificación ASCII. Vea abajo.
usar
$""
literales de extensión bash :Solo funciona para literales, por lo que no es útil para leer archivos.
Solución para las trampas
Almacene una versión codificada uuencode base64 del archivo en la variable y decodifique antes de cada uso:
Salida:
uuencode y udecode son POSIX 7 pero no en Ubuntu 12.04 por defecto (
sharutils
paquete) ... No veo una alternativa POSIX 7 para la<()
extensión de sustitución del proceso bash, excepto escribir en otro archivo ...Por supuesto, esto es lento e inconveniente, así que supongo que la respuesta real es: no use Bash si el archivo de entrada puede contener caracteres NUL.
fuente
S="$(printf "\\\'\"")"; echo $S
. Salida:\'"
. Así funciona =)$()
expansión, mi ejemplo muestra que la$()
expansión funciona\'"
.esto funciona para mi:
v=$(cat <file_path>) echo $v
fuente
Como señala Ciro Santilli, el uso de sustituciones de comandos eliminará las nuevas líneas finales. Su solución para agregar caracteres finales es excelente, pero después de usarla durante bastante tiempo decidí que necesitaba una solución que no utilizara la sustitución de comandos.
Mi enfoque ahora usa
read
junto con la banderaprintf
incorporada para leer el contenido de stdin directamente en una variable.-v
Esto admite entradas con o sin líneas nuevas.
Ejemplo de uso:
fuente
_contents="${_contents}${_line}\n "
preservar nuevas líneas?$'\n'
? Eso es necesario, de lo contrario, está agregando literales\
yn
caracteres. Su bloque de código también tiene un espacio adicional al final, no estoy seguro si eso es intencional, pero sangraría cada línea posterior con un espacio en blanco adicional.Puede acceder a 1 línea a la vez por bucle
Copie todo el contenido en Archivo (por ejemplo, line.sh); Ejecutar
fuente
for
bucle no se repite sobre las líneas, se repite sobre las palabras. En el caso de/etc/passwd
, sucede que cada línea contiene solo una palabra. Sin embargo, otros archivos pueden contener varias palabras por línea.