web-dev-qa-db-fra.com

Quel est l'intérêt d'ajouter une nouvelle ligne à la fin d'un fichier?

Certains compilateurs (en particulier ceux en C ou C++) vous avertissent:

No new line at end of file

Je pensais que ce serait un problème réservé aux programmeurs C, mais github affiche un message dans la vue de validation:

\ No newline at end of file

pour un fichier PHP.

Je comprends la chose du préprocesseur expliquée dans ce fil , mais qu'est-ce que cela a à voir avec PHP? Est-ce la même chose include() ou est-ce lié à la rubrique \r\n Vs \n?

Quel est l'intérêt d'avoir une nouvelle ligne à la fin d'un fichier?

197
Philipp Stephan

Il ne s'agit pas d'ajouter une nouvelle ligne supplémentaire à la fin d'un fichier, il ne s'agit pas de supprimer la nouvelle ligne qui devrait être là.

Un fichier texte , sous unix, consiste en une série de lignes , chacune se terminant par un caractère de nouvelle ligne (\n). Un fichier qui n'est pas vide et ne se termine pas par une nouvelle ligne n'est donc pas un fichier texte.

Les utilitaires qui sont censés fonctionner sur des fichiers texte peuvent ne pas bien gérer les fichiers qui ne se terminent pas par une nouvelle ligne; les utilitaires historiques Unix peuvent ignorer le texte après la dernière nouvelle ligne, par exemple. GNU les utilitaires ont une politique de comportement décent avec les fichiers non textuels, tout comme la plupart des autres utilitaires modernes, mais vous pouvez toujours rencontrer un comportement étrange avec les fichiers qui sont manque une dernière ligne¹.

Avec GNU diff, si l'un des fichiers comparés se termine par une nouvelle ligne mais pas l'autre, il est important de noter ce fait. Comme diff est orienté ligne, il ne peut pas l'indiquer) en stockant une nouvelle ligne pour l'un des fichiers mais pas pour les autres - les nouvelles lignes sont nécessaires pour indiquer où chaque ligne dans le fichier diff commence et se termine. Donc diff utilise ce texte spécial \ No newline at end of file pour différencier un fichier qui ne s'est pas terminé par une nouvelle ligne d'un fichier qui l'a fait.

Soit dit en passant, dans un contexte C, un fichier source se compose également d'une série de lignes. Plus précisément, une unité de traduction est considérée dans une implémentation définie comme une série de lignes, dont chacune doit se terminer par un caractère de nouvelle ligne ( n1256 §5.1.1.1). Sur les systèmes Unix, le mappage est simple. Sous DOS et Windows, chaque séquence CR LF (\r\n) est mappé sur une nouvelle ligne (\n; c'est ce qui se passe toujours lors de la lecture d'un fichier ouvert sous forme de texte sur ces OS). Il existe quelques systèmes d'exploitation qui n'ont pas de caractère de nouvelle ligne, mais qui ont plutôt des enregistrements de taille fixe ou variable; sur ces systèmes, le mappage des fichiers vers la source C introduit un \n à la fin de chaque enregistrement. Bien que cela ne soit pas directement pertinent pour Unix, cela signifie que si vous copiez un fichier source C qui manque sa nouvelle ligne finale vers un système avec des fichiers texte basés sur des enregistrements, puis copiez-le à nouveau, vous vous retrouverez soit avec le incomplet dernière ligne tronquée lors de la conversion initiale, ou une nouvelle ligne supplémentaire ajoutée lors de la conversion inverse.

¹ Exemple: la sortie de GNU sort se termine toujours par une nouvelle ligne. Donc, si le fichier foo manque sa dernière ligne finale, vous constaterez que sort foo | wc -c signale un caractère de plus que cat foo | wc -c.

Pas nécessairement la raison, mais une conséquence pratique du fait que les fichiers ne se terminent pas par une nouvelle ligne:

Considérez ce qui se passerait si vous vouliez traiter plusieurs fichiers à l'aide de cat. Par exemple, si vous vouliez trouver le mot foo au début de la ligne dans 3 fichiers:

cat file1 file2 file3 | grep -e '^foo'

Si la première ligne du fichier3 commence par foo, mais que le fichier2 n'a pas de \n Final après sa dernière ligne, cette occurrence ne sera pas trouvée par grep, car la dernière ligne du fichier2 et le la première ligne du fichier3 serait vue par grep comme une seule ligne.

Donc, par cohérence et afin d'éviter les surprises, j'essaie de garder mes fichiers se terminant toujours par une nouvelle ligne.

48
Sergio Acosta

Il y a deux aspects:

  1. Certains compilateurs C ne peuvent pas analyser la dernière ligne si elle ne se termine pas par une nouvelle ligne. La norme C spécifie qu'un fichier C doit se terminer par une nouvelle ligne (C11, 5.1.1.2, 2.) et qu'une dernière ligne sans nouvelle ligne produit un comportement indéfini (C11, J.2, 2e élément). Peut-être pour des raisons historiques, car certains fournisseurs d'un tel compilateur faisaient partie du comité lors de la rédaction de la première norme. D'où l'avertissement du GCC.

  2. diff programmes (comme ceux utilisés par git diff, github etc.) montrent les différences ligne par ligne entre les fichiers. Ils affichent généralement un message lorsqu'un seul fichier se termine par un retour à la ligne, sinon vous ne verriez pas cette différence. Par exemple, si la seule différence entre deux fichiers est la présence du dernier caractère de nouvelle ligne, sans l'indication, il semblerait que les deux fichiers soient identiques, lorsque diff et cmp renvoient une sortie- coder le succès inégal et les sommes de contrôle des fichiers (par exemple via md5sum) ne correspondent pas.

17
maxschlepzig

Le \ No newline at end of file Que vous obtenez de github apparaît à la fin d'un patch (au format diff , voir la note à la fin de la section "Format unifié").

Les compilateurs ne se soucient pas de la présence ou non d'une nouvelle ligne à la fin d'un fichier, mais git (et les utilitaires diff/patch) doivent en tenir compte. . Il y a plusieurs raisons à cela. Par exemple, oublier d'ajouter ou de supprimer une nouvelle ligne à la fin d'un fichier changerait son hachage (md5sum/sha1sum). De plus, les fichiers ne sont pas toujours des programmes, et un \n Final peut faire une différence.

Remarque : À propos de l'avertissement des compilateurs C, je suppose qu'ils insistent pour une nouvelle ligne finale à des fins de compatibilité descendante. Les très anciens compilateurs peuvent ne pas accepter la dernière ligne s'ils ne se terminent pas par \n (Ou une autre séquence de caractères de fin de ligne dépendante du système).

12
Stéphane Gimenez

Il y a aussi l'intérêt de garder l'historique des différences. Si un fichier se termine sans caractère de nouvelle ligne, l'ajout de tout à la fin du fichier sera considéré par les utilitaires diff comme modifiant cette dernière ligne (car \n y est ajouté).

Cela pourrait entraîner des résultats indésirables avec des commandes telles que git blame et hg annotate.

6
Hosam Aly

POSIX, il s'agit d'un ensemble de normes spécifiées par l'IEEE pour maintenir la compatibilité entre les systèmes d'exploitation.

L'une d'elles est la définition d'une "ligne" étant une séquence de zéro ou plusieurs non-caractères plus un caractère de fin de ligne.

Ainsi, pour que cette dernière ligne soit reconnue comme une "ligne" réelle, elle doit avoir un nouveau caractère de fin de ligne.

Ceci est important si vous dépendez des outils du système d'exploitation pour dire le nombre de lignes ou diviser/aider à analyser votre fichier. Étant donné PHP est un langage de script, c'est tout à fait possible, surtout à ses débuts ou même maintenant (je n'ai aucune idée/postulat), il avait des dépendances de système d'exploitation comme ça.

En réalité, la plupart des systèmes d'exploitation ne sont pas entièrement compatibles POSIX et les humains ne sont pas comme cette machine ou ne se soucient même pas de terminer de nouvelles lignes. Donc, pour la plupart des choses, c'est un smorgasbord de tout ce qui se soucie de lui, l'avertissement ou tout simplement aller que le dernier morceau de texte est vraiment une ligne, alors incluez-le.

4
user3379747