2011-12-20 29 views
10

Hay dos maneras de leer un archivo línea por línea que quiero discutir aquí:Bash bucle while que lee archivo línea por línea

#!/bin/bash  

while read line  
do  
    echo-e "$ line \ n"  
done <file.txt 

y

#!/bin/bash  
exec 3<file.txt 

while read line  
do  
    echo-e "$ line \ n"  
done 

Así primera versión funciona bien pero no entiendo el mecanismo de trabajo mientras bucle con el archivo. Pero el mecanismo de la segunda versión lo entiendo. Pero aquí no entiendo por qué se cuelga y no imprime nada.

Respuesta

9

El primer bucle funciona porque la redirección después de done se aplica a todo el bucle, por lo que el read está leyendo desde el archivo, no desde la entrada estándar del script.

La segunda versión se cuelga porque read lee desde el descriptor de archivo 0, que es una entrada estándar, y no ha escrito nada allí. La línea exec redirige 3 descriptor de archivo para la lectura del archivo, pero no estás leyendo de descriptor de archivo 3.

Se podía rescatar a la segunda mediante el uso de:

exec <file.txt 

de entrada estándar Ahora se lee desde el archivo nombrado.

3

Hay algunos errores en sus scripts.

  1. Espacio entre $ y nombre de la variable. (puede ser una mala edición)
  2. Espacio entre echo y -e. (puede ser una edición incorrecta)
  3. Mencionando la lectura en un descriptor de archivo donde el archivo está abierto. Estás leyendo el archivo en el descriptor 0 y exec se está ejecutando en el descriptor 3.

Debe ser algo como esto -

#!/bin/bash  
exec 3<file.txt 

while read line 
do 
    echo -e "$line \n" 
done <&3 
+1

¿El '<3' y en el trabajo de la línea' read'? Solía ​​ser el caso, en los malos tiempos del verdadero shell de Bourne, que la redirección se haría cada vez que pasa el bucle, por lo que obtuviste efectos divertidos (como que el archivo se cierra en cada iteración). Puedo creer que ha sido modificado desde entonces para que las cosas funcionen un poco más sensatamente. * FWIW *: cuando probé 'bash' en MacOS X, con:' while read line

+0

Gracias Jon, probé con el script anterior, funcionó en mi mac. http://cl.ly/ClDf pero esa es información útil. Lo recordaré. Todavía soy muy nuevo en bash.Acabo de aprender 'awk' y' sed'. Pero comenzará algunos libros sobre fundamentos de bash. :) –

+0

Han editado la respuesta para tener '<& 3' después de la instrucción' done' en lugar de la instrucción 'read'. –

4

Esto podría funcionar para usted:

exec 3<file.txt 

while read -u3 line 
do 
    echo -e "$line \n" 
done 

-u3 lee desde el descriptor de archivo 3

Extraño que echo no tiene el interruptor del complemento lik e ksh's print comando.

0

-U3 es ideal para mi propósito (lectura solamente la siguiente línea)

#!/bin/bash 

logs=(*Logs.txt) 
[[ -e "${logs[0]}" ]] || exit 0 

exec 3<"${logs[0]}" 

while read -u3 line 
do 
     if [[ $(echo "$line"| grep -c SCSI_STATUS_CHECK_CONDITION) -eq 1 ]]; then 
       read -u3 line 
       echo "$line" 
     fi 
done 
Cuestiones relacionadas