bash - linea - Leer un archivo línea por línea asignando el valor a una variable
leer archivo con shell script (9)
El uso de la siguiente plantilla de Bash debería permitirle leer un valor a la vez de un archivo y procesarlo.
while read name; do
# Do what you want to $name
done < filename
Tengo el siguiente archivo .txt:
Marco
Paolo
Antonio
Quiero leerlo línea por línea, y para cada línea quiero asignar un valor de línea .txt a una variable. Suponiendo que mi variable es $name
, el flujo es:
- Lea la primera línea del archivo
- Asigne
$name
= "Marco" - Hacer algunas tareas con
$name
- Lea la segunda línea del archivo
- Asigne
$name
= "Paolo"
Le animo a usar la -r
para read
que significa:
-r Do not treat a backslash character in any special way. Consider each
backslash to be part of the input line.
Estoy citando del man 1 read
.
Otra cosa es tomar un nombre de archivo como argumento.
Aquí está el código actualizado:
#!/usr/bin/bash
filename="$1"
while read -r line; do
name="$line"
echo "Name read from file - $name"
done < "$filename"
Leí la pregunta como:
"Si quiero leer un archivo usando expect ¿cómo debería hacerlo? Quiero hacerlo porque cuando escribí ''haciendo algunas tareas con $ nombre'', quise decir que mis tareas son comandos de espera".
Lea el archivo desde dentro de sí mismo:
suExpectScript:
#!/usr/bin/expect
# Pass in filename from command line
set filename [ lindex $argv 0 ]
# Assumption: file in the same directory
set inFile [ open $filename r ]
while { ! [ eof $inFile ] } {
set line [ gets $inFile ]
# You could set name directly.
set name $line
# Do other expect stuff with $name ...
puts " Name: $name"
}
close $inFile
Entonces llámalo como:
yourExpectScript file_with_names.txt
Lo siguiente (guardar como rr.sh
) lee un archivo pasado como un argumento línea por línea:
#!/bin/bash
while IFS='''' read -r line || [[ -n "$line" ]]; do
echo "Text read from file: $line"
done < "$1"
Explicación:
-
IFS=''''
(oIFS=
) evita que se recorten los espacios en blanco iniciales o finales. -
-r
impide que se interpreten los escapes de barra invertida. -
|| [[ -n $line ]]
|| [[ -n $line ]]
evita que la última línea sea ignorada si no termina con un/n
(ya que laread
devuelve un código de salida distinto de cero cuando encuentra EOF).
Ejecute el script de la siguiente manera:
chmod +x rr.sh
./rr.sh filename.txt
....
Muchas personas han publicado una solución que está demasiado optimizada. No creo que sea incorrecto, pero humildemente creo que una solución menos optimizada será deseable para permitir que todos comprendan fácilmente cómo funciona esto. Aquí está mi propuesta:
#!/bin/bash
#
# This program reads lines from a file.
#
end_of_file=0
while [[ $end_of_file == 0 ]]; do
read -r line
# the last exit status is the
# flag of the end of file
end_of_file=$?
echo $line
done < "$1"
Para el correcto manejo de errores:
#!/bin/bash
set -Ee
trap "echo error" EXIT
test -e ${FILENAME} || exit
while read -r line
do
echo ${line}
done < ${FILENAME}
Si necesita procesar el archivo de entrada y la entrada del usuario (o cualquier otra cosa desde la entrada estándar), use la siguiente solución:
#!/bin/bash
exec 3<"$1"
while IFS='''' read -r -u 3 line || [[ -n "$line" ]]; do
read -p "> $line (Press Enter to continue)"
done
Basado en la respuesta aceptada y en el tutorial de redireccionamiento de hackers de bash .
Aquí, abrimos el descriptor de archivo 3 para el archivo pasado como el argumento del script y le decimos a la read
que use este descriptor como entrada ( -u 3
). Por lo tanto, dejamos el descriptor de entrada predeterminado (0) adjunto a un terminal u otra fuente de entrada, capaz de leer la entrada del usuario.
Utilizar:
filename=$1
IFS=$''/n''
for next in `cat $filename`; do
echo "$next read from $filename"
done
exit 0
Si ha configurado IFS
diferente, obtendrá resultados impares.
#! /bin/bash
cat filename | while read LINE; do
echo $LINE
done