Pourquoi unix en lecture ne lit-il pas la dernière ligne?

Mon script

export IFS=":" cat hello | while read abcd; do echo $a,$b,$c,$d done 

Mon dossier hello

 1:1:1:1 2:2:2:2 3:3:3:3 

Ma sortie

 1,1,1,1 2,2,2,2 

Si je mets une ligne blanche après 3:3:3:3 dans hello la sortie devient

 1,1,1,1 2,2,2,2 3,3,3,3 

Quelqu’un sait comment je peux résoudre ce problème, donc je n’ai pas besoin de mettre une ligne blanche à la fin du hello ?

Ce qui se passe est que la commande read échoue lorsque l’entrée n’est pas terminée par une nouvelle ligne. Comme le caractère de nouvelle ligne est manquant à la fin de votre fichier, la read échoue, de sorte que la dernière itération de la boucle while est ignorée.

Si vous ne voulez pas / ne pouvez pas vous assurer que votre fichier d’entrée comporte une nouvelle ligne à la fin, vous pouvez regrouper votre cat avec un echo pour donner l’apparence d’une entrée terminée par newline, par exemple comme ceci:

 { cat hello; echo; } | while read abcd; do echo $a,$b,$c,$d done 

ou comme ça:

 (cat hello; echo) | while read abcd; do echo $a,$b,$c,$d done 

Il existe un hack méconnu et peu connu pour append une nouvelle ligne manquante à un stream de texte si et seulement si elle manque:

 sed '$a\' 

Voir cette discussion sur unix.stackexchange, par exemple.

Ceci est une lecture approfondie pour la question pourquoi?

Si vous ne voulez pas mettre une nouvelle ligne à la fin, vous pouvez le faire:

 while IFS=: read -rabcd || [ -n "$a" ]; do echo $a,$b,$c,$d; done < file 

Ou en utilisant grep :

 while IFS=: read -rabcd; do echo $a,$b,$c,$d; done < <(grep "" filee) 

Remarque:

  1. Il n'y a pas besoin d'utiliser le chat avec la boucle while.
  2. Vous devriez presque toujours utiliser l'option -r avec read.

Cela est probablement dû à l’absence de caractère de nouvelle ligne après la dernière ligne du fichier d’entrée.

Exécutez cette commande pour découvrir:

 cat -vte hello 

Et voyez ce que vous obtenez.

Votre fichier manque probablement une nouvelle ligne ( \n ) sur la dernière ligne. Vous pouvez le prouver en imprimant les valeurs résiduelles de $a , etc.

 while IFS=: read abcd; do echo $a,$b,$c,$d; done < hello echo $a,$b,$c,$d 

Corrigez le fichier. En outre, vous devriez pouvoir définir IFS spécifiquement pour la read comme indiqué ci-dessus. Et pas besoin de cat le fichier non plus, utilisez simplement la redirection d'entrée comme indiqué