Pourquoi les fichiers texte devraient-ils se terminer par une nouvelle ligne?

je suppose que tout le monde ici est familier avec l'adage que tous les fichiers texte doivent se terminer par une nouvelle ligne. Je connais cette "règle" depuis des années mais je me suis toujours demandé-pourquoi?

1128
demandé sur codeforester 2009-04-08 16:16:39
la source

17 ответов

parce que c'est comment la norme POSIX définit une" ligne 151950920 151970920":

3.206 ligne Une séquence de caractères non nuls ou plus, plus un caractère final.

par conséquent, les lignes ne se terminant pas par un caractère newline ne sont pas considérées comme des lignes réelles. C'est pourquoi certains programmes ont des problèmes pour traiter la dernière ligne d'un fichier si ce n'est pas newline résilié.

il y a au moins un avantage important à cette ligne directrice lorsqu'on travaille sur un émulateur de terminal: tous les outils Unix attendent cette convention et travaillent avec elle. Par exemple , lorsque vous concaténez des fichiers avec cat , un fichier terminé par newline aura un effet différent de celui sans:

$ more a.txt
foo$ more b.txt
bar
$ more c.txt
baz
$ cat *.txt
foobar
baz

et, comme le montre l'exemple précédent, lors de l'affichage du fichier sur la ligne de commande (par exemple via more ), un de retour à la ligne terminée par le fichier de résultats dans un affichage correct. Un dossier mal classé peut être confus (deuxième ligne).

pour des raisons de cohérence, il est très utile de suivre cette règle – faire autrement entraînera un surcroît de travail lors du traitement des outils Unix par défaut.

maintenant, sur non conforme POSIX systèmes (de nos jours qui est principalement Windows), le point est sans objet: les fichiers ne se terminent généralement pas par une nouvelle ligne, et la (informelle) la définition d'une ligne pourrait par exemple être "texte qui est séparé par des lignes nouvelles" (Notez l'emphase). C'est tout à fait valable. Toutefois, pour les données structurées (par exemple Code de programmation), cela rend l'analyse un peu plus compliquée: cela signifie généralement que les analyseurs doivent être réécrits. Si un analyseur a été écrit à l'origine avec la définition POSIX à l'esprit, alors il pourrait être plus facile de modifier le flux de tokens plutôt que l'analyseur - en d'autres termes, ajouter un " NEWLINE artificiel" jeton à la fin de l'entrée.

1065
répondu Konrad Rudolph 2017-11-22 13:11:57
la source

chaque ligne doit être terminée par un caractère newline, y compris le dernier. Certains programmes ont des problèmes de traitement de la dernière ligne d'un fichier s'il n'est pas newline terminé.

GCC avertit non pas parce qu'il ne peut pas traiter le fichier, mais parce qu'il doit dans le cadre de la norme.

la norme linguistique C dit Un fichier source qui n'est pas vide prend fin dans un caractère de nouvelle ligne, qui ne doit pas être immédiatement précédée d'une barre oblique inverse.

Puisque c'est une clause, nous devons émettre un message de diagnostic pour une violation de cette règle.

voir la section 2.1.1.2 de la norme ANSI C 1989. Section 5.1.1.2 de la norme ISO C 1999 (et probablement aussi de la norme ISO c 1990).

référence: the GCC/GNU mail archive .

249
répondu Bill the Lizard 2009-04-08 16:26:46
la source

Cette réponse est une tentative de réponse technique plutôt que de l'opinion.

si nous voulons être des puristes de POSIX, nous définissons une ligne comme:

séquence d'au moins zéro caractère non- plus un caractère final.

Source: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_206

Une ligne incomplète comme:

séquence d'un ou de plusieurs caractères non- à la fin du fichier.

Source: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_195

Un fichier texte comme:

un fichier qui contient des caractères organisés en zéro ou plus de lignes. Les lignes ne contiennent pas NUL les caractères et aucun ne peut dépasser les octets {LINE_MAX} en longueur, y compris le caractère . Bien que POSIX.1-2008 ne fait pas de distinction entre les fichiers texte et les fichiers binaires (voir la norme ISO C), de nombreux utilitaires ne produisent des résultats prévisibles ou significatifs que lorsqu'ils fonctionnent sur des fichiers texte. Les utilitaires standards qui ont de telles restrictions spécifient toujours "text files" dans leurs sections STDIN ou INPUT FILES.

Source: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_397

Une chaîne de caractères comme:

séquence contiguë d'octets se terminant par et incluant le premier octet nul.

Source: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_396

de ceci donc, nous pouvons déduire que le ce n'est que si nous traitons de la notion de ligne d'un fichier ou d'un fichier comme un fichier texte (étant qu'un fichier texte est une organisation de zéro ou plus lignes, et une ligne que nous connaissons doit se terminer avec un ).

Affaire au point: wc -l filename .

du manuel wc nous lisons:

Une ligne est définie comme une chaîne de caractères délimitée par un caractère.

quelles sont les implications pour les fichiers JavaScript, HTML, et CSS étant alors qu'ils sont texte fichiers?

dans les navigateurs, IDEs modernes, et d'autres applications front-end il n'y a pas de problèmes avec le saut de fin de vie à L'EOF. Les applications analyseront les fichiers correctement. Il a depuis tous les systèmes D'exploitation ne sont pas conformes à la norme POSIX, de sorte qu'il ne serait pas pratique pour les outils autres que le système D'exploitation (p. ex. les navigateurs) de traiter les fichiers selon la norme POSIX (ou toute norme de niveau OS).

par conséquent, nous pouvons être relativement sûrs qu'EOL at EOF n'aura pratiquement aucun impact négatif au niveau de l'application - peu importe si elle tourne sur un système D'exploitation UNIX.

à ce point nous pouvons dire avec confiance que sauter la fin de vie à L'EOF est sûr quand traiter avec JS, HTML, CSS côté client. En fait, nous pouvons affirmer que la minification de n'importe lequel de ces fichiers, ne contenant pas est sûre.

nous pouvons aller plus loin et dire qu'en ce qui concerne NodeJS il ne peut pas adhérer à la norme POSIX étant qu'il peut fonctionner dans des environnements non conformes à POSIX.

Que reste-t-il alors? Le système de niveau de l'outillage.

cela signifie les seules questions qui peuvent arise sont avec des outils qui font un effort pour adhérer leur fonctionnalité à la sémantique de POSIX (par exemple la définition d'une ligne comme indiqué dans wc ).

même ainsi, tous les shells n'adhéreront pas automatiquement à POSIX. Bash, par exemple, ne fait pas défaut à POSIX behavior. Il y a un commutateur pour l'activer: POSIXLY_CORRECT .

matière à réflexion sur la valeur de la fin de vie : http://www.rfc-editor.org/EOLstory.txt

en restant sur la piste de l'outillage, à toutes fins pratiques, considérons ceci:

travaillons avec un fichier qui n'a pas de fin de vie. De cette écriture le fichier dans cet exemple est un minifiés JavaScript sans EOL.

curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o x.js
curl http://cdnjs.cloudflare.com/ajax/libs/AniJS/0.5.0/anijs-min.js -o y.js

$ cat x.js y.js > z.js

-rw-r--r--  1 milanadamovsky   7905 Aug 14 23:17 x.js
-rw-r--r--  1 milanadamovsky   7905 Aug 14 23:17 y.js
-rw-r--r--  1 milanadamovsky  15810 Aug 14 23:18 z.js

notez que la taille du fichier cat est exactement la somme de ses différentes parties. Si la concaténation des fichiers JavaScript est une préoccupation pour les fichiers JS, la préoccupation la plus appropriée serait soit de démarrer chaque fichier JavaScript avec un point-virgule.

comme quelqu'un d'autre a mentionné dans ce thread: et si vous voulez cat deux fichiers dont la sortie devient juste une ligne au lieu de deux? En d'autres termes, cat est ce qu'il est censé faire.

le man de cat ne mentionne que la lecture des entrées jusqu'à L'EOF, pas . Notez que le commutateur -n de cat affichera également un non- < newline> ligne terminée (ou ligne incomplète ) comme une ligne - étant que le compte commence à 1 (selon le man .)

- n numéroter les lignes de sortie, en commençant par 1.

maintenant que nous comprenons comment POSIX définit une "ligne , ce comportement devient ambigu, ou vraiment non conforme.

comprendre le but et la conformité d'un outil donné aidera à déterminer à quel point il est essentiel de terminer les fichiers avec une fin de vie. En C, C++, Java (JARs), etc... certaines normes dicteront une nouvelle ligne pour la validité - aucune norme de ce genre n'existe pour JS, HTML, CSS.

par exemple, au lieu d'utiliser wc -l filename on pourrait faire awk '{x++}END{ print x}' filename , et soyez assuré que le succès de la tâche n'est pas menacé par un fichier que nous pourrions vouloir traiter que nous n'avons pas écrit (par exemple un troisième Bibliothèque du parti comme le minified JS nous curl d) - à moins que notre intention était vraiment de compter lignes dans le sens conforme POSIX.

Conclusion

il y aura très peu de cas d'utilisation réelle où sauter EOL at EOF pour certains fichiers texte tels que JS, HTML, et CSS aura un impact négatif - si tant est qu'il y en ait. Si nous nous en remettons à la présence de , nous limitons la fiabilité de notre outillage uniquement aux fichiers que nous créons et nous ouvrir à des erreurs potentielles introduites par des fichiers tiers.

Morale de l'histoire: Ingénieur de l'outillage qui n'ont pas la faiblesse de s'appuyer sur EOL à l'EOF.

N'hésitez pas à poster les cas d'utilisation tels qu'ils s'appliquent à JS, HTML et CSS où nous pouvons examiner comment sauter la fin de vie a un effet négatif.

91
répondu Milan Adamovsky 2014-08-15 10:47:08
la source

elle peut être liée à la différence entre :

  • fichier texte (chaque ligne est censée se terminer en fin de ligne)
  • fichier binaire (il n'y a pas de vraies "lignes", et la longueur du fichier doit être préservée)

Si chaque ligne ne bout en bout de ligne, cela évite, par exemple, que la concaténation de deux fichiers texte rendrait la dernière ligne de la première manche en la première ligne de la deuxième.

de plus, un éditeur peut vérifier au chargement si le fichier se termine en fin de ligne, l'enregistre dans son option locale "eol", et l'utilise lors de l'écriture du fichier.

"151910920 y A quelques années (2005), de nombreux éditeurs (ZDE, Eclipse, Scite, ...) a "oublié "cette fin de semaine, qui n'était pas très appréciée .

Non seulement cela, mais ils ont mal interprété cette fin de vie, comme " Commencer un nouveau ligne et de commencer à afficher une autre ligne comme si elle existait déjà.

Ceci était très visible avec un fichier texte 'correct' avec un éditeur de texte bien comporté comme vim, comparé à l'ouvrir dans l'un des éditeurs ci-dessus. Il a affiché une ligne supplémentaire sous la dernière ligne réelle du fichier. Vous voyez quelque chose comme ceci:

1 first line
2 middle line
3 last line
4
59
répondu VonC 2014-02-04 15:30:07
la source

certains outils s'y attendent. Par exemple, wc s'attend à ce que:

$ echo -n "Line not ending in a new line" | wc -l
0
$ echo "Line ending with a new line" | wc -l
1
39
répondu Flimm 2011-10-12 18:16:58
la source

fondamentalement, il y a beaucoup de programmes qui ne traiteront pas les fichiers correctement s'ils n'obtiennent pas l'EOL EOF finale.

GCC vous avertit à ce sujet parce qu'il est prévu dans le cadre de la norme C. (section 5.1.1.2 apparemment)

"Pas de saut de ligne à la fin du fichier" avertissement du compilateur

18
répondu cgp 2017-05-23 15:02:49
la source

cela provient des premiers jours où des terminaux simples ont été utilisés. Le newline char a été utilisé pour déclencher une "chasse d'eau" des données transférées.

Aujourd'hui, le newline char n'est plus nécessaire. Bien sûr, beaucoup d'applications ont encore des problèmes si la nouvelle ligne n'est pas là, mais je considère que c'est un bug dans ces applications.

si toutefois vous avez un format de fichier texte où vous exiger la nouvelle ligne, vous obtenez simple vérification des données très bon marché: si le fichier se termine par une ligne qui n'a pas de nouvelle ligne à la fin, vous savez que le fichier est cassé. Avec seulement un octet supplémentaire pour chaque ligne, vous pouvez détecter des fichiers cassés avec une grande précision et presque pas de temps CPU.

12
répondu Stefan 2009-04-08 16:41:21
la source

un cas d'utilisation séparé: lorsque votre fichier texte est contrôlé par version (dans ce cas précis sous git bien qu'il s'applique à d'autres aussi). Si du contenu est ajouté à la fin du fichier, alors la ligne qui était auparavant la dernière ligne aura été modifiée pour inclure un caractère newline. Cela signifie que blame dans le fichier pour savoir quand cette ligne a été éditée pour la dernière fois montrera l'ajout de texte, pas la propagation avant que vous vouliez réellement voir.

11
répondu Robin Whittleton 2017-03-29 21:55:59
la source

il y a aussi un problème de programmation pratique avec les fichiers qui manquent de nouvelles lignes à la fin: le Bash read intégré (Je ne sais pas d'autres read implémentations) ne fonctionne pas comme prévu:

printf $'foo\nbar' | while read line
do
    echo $line
done

l'impression seulement foo ! La raison en est que lorsque read rencontre la dernière ligne, il écrit le contenu à $line mais renvoie le code de sortie 1 parce qu'il a atteint EOF. Cela brise le while boucle, donc on n'atteint jamais la partie echo $line . Si vous souhaitez gérer cette situation, vous devez faire ce qui suit:

while read line || [ -n "${line-}" ]
do
    echo $line
done < <(printf $'foo\nbar')

C'est-à-dire, faire le echo si le read a échoué à cause d'une ligne non vide à la fin du fichier. Naturellement, dans ce cas, il y aura une nouvelle ligne supplémentaire dans la sortie qui n'était pas dans l'entrée.

10
répondu l0b0 2014-03-01 13:06:49
la source

sans doute simplement qu'un code d'analyse s'attendait à ce qu'il soit là.

Je ne suis pas sûr que je considérerais cela comme une" règle", et ce n'est certainement pas quelque chose que j'adhère religieusement. La plupart du code sensible saura analyser le texte (y compris les encodages) ligne par ligne (n'importe quel choix de terminaisons de ligne), avec-ou-sans une nouvelle ligne sur la dernière ligne.

en effet-si vous terminez par une nouvelle ligne: y a-t-il (en théorie) une ligne finale vide entre la fin de vie et l'EOF? L'une de réfléchir...

9
répondu Marc Gravell 2009-04-08 16:19:54
la source

en plus des raisons pratiques ci-dessus, Je ne serais pas surpris si les auteurs D'Unix (Thompson, Ritchie, et al.) ou leurs prédécesseurs Multics ont réalisé qu'il y a une raison théorique d'utiliser les terminateurs de ligne plutôt que les séparateurs de ligne: avec les terminateurs de ligne, vous pouvez encoder tous les fichiers de lignes possibles. Avec les séparateurs de ligne, il n'y a pas de différence entre un fichier de zéro ligne et un fichier contenant une seule ligne vide; les deux sont encodés comme un fichier contenant caractères nul.

donc, les raisons sont:

  1. parce que C'est ainsi que POSIX le définit.
  2. parce que certains outils s'y attendent ou "se comportent mal" sans elle. Par exemple, wc -l ne comptera pas une" ligne " finale si elle ne se termine pas par une nouvelle ligne.
  3. parce que c'est simple et pratique. Sur Unix, cat fonctionne simplement et il fonctionne sans complication. Il copie juste les octets de chaque fichier, sans besoin d'interprétation. Je ne pense pas qu'il y ait un DOS équivalent à cat . À l'aide de copy a+b c finira par fusionner la dernière ligne du fichier a avec la première ligne du fichier b .
  4. parce qu'un fichier (ou un flux) de lignes zéro peut être distingué d'un fichier d'une ligne vide.
9
répondu John Wiersba 2015-09-25 15:23:09
la source

pourquoi les fichiers (texte) devraient-ils se terminer par une nouvelle ligne?

aussi bien exprimé par beaucoup, parce que:

  1. de nombreux programmes ne se comportent pas bien, ou échouent sans elle.

  2. même les programmes qui gèrent bien un fichier manquent d'une fin '\n' , la fonctionnalité de l'outil peut ne pas répondre aux attentes de l'utilisateur - ce qui peut être imprécis dans ce cas coin.

  3. "151970920 Programmes de" rarement interdire finale '\n' (je ne sais pas du tout).


pourtant, cela nous amène à la question suivante:

que doit faire le code sur les fichiers texte sans newline?

  1. le plus important - N'écrivez pas un code qui suppose le fichier texte se termine par une nouvelle ligne . supposant un fichier conforme à un format conduit à la corruption de données, des attaques de pirates et des plantages. Exemple:

    // Bad code
    while (fgets(buf, sizeof buf, instream)) {
      // What happens if there is no \n, buf[] is truncated leading to who knows what
      buf[strlen(buf) - 1] = '"151900920"';  // attempt to rid trailing \n
      ...
    }
    
  2. si l'arrière final '\n' est nécessaire, alertez l'utilisateur de son absence et de la mesure prise. IOWs, valider le format du fichier. Note: Ceci peut inclure une limite à la longueur de ligne maximale, l'encodage des caractères, etc.

  3. définir clairement, document, le traitement par le code d'une finale manquante '\n' .

  4. Ne pas, autant que possible, générer un fichier, le manque de la fin de la '\n' .

7
répondu chux 2017-08-30 16:59:13
la source

je me le demande depuis des années. Mais j'ai trouvé une bonne raison aujourd'hui.

Imaginez un fichier avec un enregistrement sur chaque ligne (ex: un fichier CSV). Et que l'ordinateur écrivait des dossiers à la fin du dossier. Mais soudain, elle s'est écrasé. Gee était la dernière ligne complète? (pas une belle situation)

mais si nous terminons toujours la dernière ligne, alors nous le saurons (vérifiez simplement si la dernière ligne est terminée). Sinon, nous aurions probablement jeter la dernière ligne à chaque fois, juste pour être sûr.

6
répondu symbiont 2017-08-08 17:22:52
la source

j'ai toujours eu l'impression que la règle venait de l'époque où l'analyse d'un dossier sans fin était difficile. C'est-à-dire que vous finiriez par écrire du code où une fin de ligne était définie par le caractère EOL ou EOF. C'était juste plus simple de supposer qu'une ligne se terminait avec EOL.

Toutefois, je crois que la règle est dérivé de compilateurs C exigeant le retour à la ligne. Et comme indiqué sur "pas de nouvelle ligne à la fin du fichier" Avertissement du compilateur , # include ne permet pas d'ajouter un saut de ligne.

3
répondu he_the_great 2017-05-23 14:55:00
la source

Imaginez que le fichier est traité alors qu'il est encore généré par un autre processus.

ça pourrait avoir un rapport avec ça? Un drapeau qui indique que le fichier est prêt à être traité.

0
répondu Pippen_001 2009-04-08 16:36:30
la source

j'aime personnellement les nouvelles lignes à la fin des fichiers de code source.

il peut avoir son origine avec Linux ou tous les systèmes UNIX d'ailleurs. Je me souviens qu'il y avait des erreurs de compilation (gcc si Je ne me trompe pas) parce que les fichiers de code source ne se terminaient pas par une nouvelle ligne vide. Pourquoi était-il fait de cette façon, c'est à se demander.

-4
répondu User 2009-04-08 16:23:08
la source

IMHO, c'est une question de style et d'opinion personnelle.

à l'époque, je n'ai pas mis cette nouvelle. Un caractère enregistré signifie plus de vitesse grâce à ce modem de 14,4 K.

plus tard, j'ai mis cette newline pour qu'il soit plus facile de sélectionner la ligne finale en utilisant shift+downarrow.

-7
répondu Torben Gundtofte-Bruun 2009-04-08 16:38:48
la source

Autres questions sur unix file newline text-files