Yo suelo usar el comando de lectura para leer un archivo de entrada a la secuencia de comandos de shell de línea por línea. Un ejemplo de código como el que a continuación se obtiene un resultado incorrecto si una nueva línea no se ha insertado al final de la última línea en el archivo de entrada, blah.txt.

#!/bin/sh

while read line
do
echo $line
done <blah.txt

Por lo que si el archivo de entrada se lee algo así como –

One 
Two
Three
Four

y yo no pulse la tecla de retorno después de Cuatro, el guión falla al leer la última línea, y se imprime

One
Two
Three

Ahora si puedo dejar una línea en blanco después de Cuatro, como,

One 
Two
Three
Four
//blank line

la salida se imprime todas las líneas, incluyendo Cuatro. Sin embargo, este no es el caso cuando he leído una línea mediante la cat comando; todas las líneas, incluida la última que se imprime sin yo tener que agregar una línea en blanco al final.

Alguien tiene ideas sobre por qué sucede esto? Los guiones que cree la mayoría va a ser ejecutado por los demás, por lo que no es necesario que van a agregar una línea en blanco al final de cada archivo de entrada.

He estado tratando de averiguar esto para las edades; apreciaría si usted tiene cualquiera de las soluciones(por supuesto, la cat comando es uno, pero me gustaría saber la razón detrás de lectura no funciona igual de bien).

InformationsquelleAutor Caife | 2013-06-24

5 Comentarios

  1. 19

    read lee hasta que encuentra un carácter de nueva línea o el final del archivo y devuelve un valor distinto de cero código de salida si se encuentra con un fin-de-archivo. Así que es muy posible que para leer una línea y el retorno distinto de cero código de salida.

    Por consiguiente, el siguiente código no es seguro si la entrada no podría ser terminado por un salto de línea:

    while read LINE; do
      # do something with LINE
    done

    porque el cuerpo de la while no ser ejecutado en la última línea.

    Técnicamente hablando, un archivo no termina con un salto de línea no es un archivo de texto, herramientas de texto y puede fallar de manera extraña en un archivo. Sin embargo, siempre soy reacio a volver a caer en esa explicación.

    Una forma de resolver el problema es probar si lo que se lee no está vacía (-n):

    while read -r LINE || [[ -n $LINE ]]; do
      # do something with LINE
    done

    Otras soluciones incluyen el uso de mapfile para leer el archivo en una matriz de tuberías, el archivo a través de la utilidad de lo que está garantizado para terminar la última línea correctamente (grep ., por ejemplo, si usted no quiere tratar con líneas en blanco), o haciendo el proceso iterativo de procesamiento con una herramienta como awk (que generalmente es de mi preferencia).

    Nota que -r es casi seguro que se necesita en el read builtin; hace read no reinterpretar \-secuencias en la entrada.

    • Me gusta la grep . solución. Bonita y sencilla.
    • ¿qué || y [[ -n $LINE ]] significa aquí? ¿|| media O?
    • Significa «o», en el sentido de que cmd1 || cmd2 tiene éxito si cmd1 éxito o cmd2 se realiza correctamente. (El éxito significa un código de salida de 0.) read tiene éxito si se encuentra un carácter de salto de línea; [[ tiene éxito si la prueba de expresión (en este caso $LINE no está vacío) es verdadera.
    • Bien hecho, usted puede querer hablar de lo que el -n prueba de la realidad de las pruebas para — comprueba si la longitud de la cadena es distinto de cero. Mismo como [[ ! -z "${LINE}" ]].
  2. 4

    Una línea de respuesta:

    IFS=$'\n'; for line in $(cat file.txt); do echo "$line" ; done
    • gracias me ayudo…!!
    • no funcionará si usted tiene espacios en la línea de tratar como una línea separada
    • Gracias schmi por tu comentario, tienes razón, he editado la respuesta y ubicada IFS=$’\n’; la primera dice esto comando cat para utilizar sólo la nueva línea como separador. La respuesta sigue siendo una línea 🙂
    • Esto cambia el IFS de la shell actual. Y usted no debe leer con líneas de
    • Usted puede cambiar IFS más tarde con unset IFS, acerca de la eficiencia para la realiza bien sólo se requiere más memoria, como dos veces el tamaño del archivo porque lo tienen todo en la memoria pero hoy, con los avances de la memoria es barata y no es un problema. Estoy de acuerdo con usted que con archivos de gran tamaño es mejor usar un tiempo, mi respuesta fue simplemente para mostrar una línea de enfoque del problema que es algo que muchas personas quieren: simplicidad
  3. 3

    El uso de tiempo de bucle como este:

    while IFS= read -r line || [ -n "$line" ]; do
      echo "$line"
    done <file

    O el uso de grep con bucle while:

    while IFS= read -r line; do
      echo "$line"
    done < <(grep "" file)

    Utilizando grep . en lugar de grep "" se omita las líneas vacías.

    Nota:

    1. Utilizando IFS= mantiene una línea de sangría intacta.

    2. Usted siempre debe usar la opción-r con la lectura.

    3. No lea las líneas con para

    4. Archivo sin una nueva línea al final no es un estándar de unix archivo de texto.

  4. 0

    A continuación el código con Redirigido «mientras que la lectura de» bucle funciona muy bien para mí

    while read LINE
    do
          let count++
          echo "$count $LINE"
    
    done < $FILENAME
    
    echo -e "\nTotal $count Lines read"

Dejar respuesta

Please enter your comment!
Please enter your name here