J'ai du mal à comprendre un comportement étrange: vi semble ajouter une nouvelle ligne (ASCII: LF, car il s’agit d’un système Unix ( AIX )) à la fin du fichier, alors que je ne l’avais PAS spécifiquement écrit.
J'édite le fichier tel quel dans vi (en prenant soin de ne pas saisir de nouvelle ligne à la fin):
# vi foo ## Which I will finish on the char "9" and not input a last newline, then `:wq`
123456789
123456789
123456789
123456789
~
~
## When I save, the cursor is just above the last "9", and no newline was added.
J'espère que vi le sauvegardera "tel quel", donc 39 octets: 10 caractères ASCII sur chacune des trois premières lignes (numéros 1 à 9, suivis d'un saut de ligne (LF sur mon système)) et seulement 9 sur la dernière line (caractères 1 à 9, pas de nouvelle ligne / LF).
Mais il semble que lorsque je le sauvegarde il est de 40 octets (au lieu de 39), et od montre un LF final :
# wc foo
4 4 40 foo ## I expected 39 here! as I didn't add the last newline
# od -a toto
0000000 1 2 3 4 5 6 7 8 9 lf 1 2 3 4 5 6
0000020 7 8 9 lf 1 2 3 4 5 6 7 8 9 lf 1 2
0000040 3 4 5 6 7 8 9 lf
0000050
## An "lf" terminates the file?? Did vi add it silently?
Si je crée le fichier avec un printf faisant exactement ce que j'ai fait dans vi, cela fonctionnera comme prévu:
# ## I create a file with NO newline at the end:
# printf "123456789\n123456789\n123456789\n123456789" > foo2
# wc foo2 ## This one is as expected: 39 bytes, exactly as I was trying to do above with vi.
3 4 39 foo ## As expected, as I didn't add the last newline
## Note that for wc, there are only three lines!
## (So wc -l doesn't count lines; it counts the [newline] chars... Which is rather odd.)
# root@SPU0WMY1:~ ## od -a foo2
0000000 1 2 3 4 5 6 7 8 9 lf 1 2 3 4 5 6
0000020 7 8 9 lf 1 2 3 4 5 6 7 8 9 lf 1 2
0000040 3 4 5 6 7 8 9
0000047 ## As expected, no added LF.
Les deux fichiers (foo (40 caractères) et foo2 (39 caractères) apparaissent exactement de la même manière si je les rouvre avec vi ...
Et si j'ouvre foo2 (39 caractères, sans nouvelle ligne) dans vi et que je me contente de le :wq
modifier , il dit qu'il écrit 40 caractères et que le saut de ligne apparaît!
Je ne peux pas avoir accès à un vi plus récent (je le fais sous AIX, vi (pas Vim ) version 3.10 je pense? (Pas de "version" ou autre moyen de le savoir)).
# strings /usr/bin/vi | grep -i 'version.*[0-9]'
@(#) Version 3.10
Est-il normal que vi (et peut-être pas dans une version plus récente? Ou Vim?) Ajoute silencieusement une nouvelle ligne à la fin d'un fichier? (Je pensais que le ~ indiquait que la ligne précédente ne finissait pas par une nouvelle ligne.)
-
Edit: quelques mises à jour supplémentaires et un peu de résumé, avec un grand merci aux réponses ci-dessous:
vi ajoute silencieusement une nouvelle ligne au moment où il écrit un fichier qui en manque (sauf si le fichier est vide).
il ne le fait qu'au moment de l'écriture! (c.-à-d. jusqu'à ce que: w, vous puissiez utiliser: e pour vérifier que le fichier est toujours tel que vous l'avez ouvert ... (c.-à-d. qu'il affiche toujours "nom du fichier" [la dernière ligne n'est pas complète] N ligne, caractère M). Lorsque vous sauvegardez, une nouvelle ligne est ajoutée silencieusement, sans avertissement spécifique (le nombre d'octets sauvegardés est indiqué, mais dans la plupart des cas, cela ne suffit pas de savoir qu'une nouvelle ligne a été ajoutée) (merci à @jiliagre de m'avoir parlé de la En ouvrant le message vi, cela m’a aidé à trouver un moyen de savoir quand le changement se produit réellement)
Ceci (correction silencieuse) est le comportement POSIX ! (voir la réponse @ barefoot-io pour les références)
vi
version ou au moins un indice sur son origine en exécutant la:ve
commande.ex
page de manuel où la:ver
commande est normalement documentée.Réponses:
C'est le
vi
comportement attendu .Votre fichier comporte une dernière ligne incomplète, donc à proprement parler (c’est-à-dire selon la norme POSIX), il ne s’agit pas d’un fichier texte, mais d’un fichier binaire.
vi
qui est un éditeur de fichier texte, pas un binaire, le corrige gracieusement lorsque vous enregistrez.Cela permet à d’autres outils de fichiers texte tels que
wc
,sed
et , de fournir le résultat attendu. Notez que cevi
n'est pas silencieux sur le problème:Remarque, pour obtenir des indices sur ce que
vi
version que vous utilisez, vous pouvez utiliser la:ve
commande. Cela montre ici que j'utilise un SVR4 hérité ici, certainement pasvim
:Apparemment, le vôtre dit:
Cela signifie probablement que AIX
vi
est basé sur le code source SVR3.En tout état de cause, ce comportement et le
[Incomplete last line]
message d'avertissementvi
figurent dans le code source de Bill Joy hérité depuis 1979 au moins et AFAIK, conservés dans toutes les branches créées à partir de versions de code source de System V, à partir desquelles des systèmes Unix propriétaires, tels qu'AIX, ont été créés.Chronologiquement, ce comportement n’est donc pas une conséquence de la conformité à POSIX, mais bien une conséquence de la décision initiale de Bill Joy d’aider les utilisateurs à modifier des fichiers texte fictifs, puis, dix ans plus tard, de la décision du comité POSIX de conserver cette tolérance.
Si vous utilisez à la
ed
place devi
, vous remarquerez que la première est plus détaillée sur le problème, du moins si voused
venez de SVR3 ou d'une branche source plus récente:Notez également qu'un fichier vide est un fichier texte valide qui ne contient aucune ligne. Comme il n’existe alors aucune ligne non terminée à corriger,
vi
n’ajoutez pas de nouvelle ligne lors de l’enregistrement du fichier.la source
vi
exactement comme le fait l'OP, bien que sous Unix différent. Ce n'est pasvim
ou un autre clone. Réponse mise à jour pour clarifier cela.vi
mise en œuvre. Peut-être SVR3. Êtes-vous sûr qu'il n'y a pas de[Incomplete last line]
message lorsque vous ouvrez le fichier?vi
implémentation AIX : www-01.ibm.com/support/docview.wss?uid=isg1IZ27694POSIX requiert ce comportement, ce qui n’a donc rien d’inhabituel.
Du manuel POSIX vi :
Suivre la piste jusqu'au manuel ex POSIX :
La section OUTPUT FILES du manuel vi redirige également vers ex:
Une paire de définitions POSIX:
Ces définitions dans le contexte de ces extraits de page de manuel signifient que, même si une implémentation conforme ex / vi doit accepter un fichier texte mal formé si la seule déformation de ce fichier est une nouvelle ligne finale absente, le résultat doit être un fichier texte valide lors de l'écriture de la mémoire tampon de ce fichier.
Bien que cet article fasse référence à l'édition 2013 du standard POSIX, les stipulations pertinentes apparaissent également dans l'édition beaucoup plus ancienne de 1997 .
Enfin, si vous trouvez que la nouvelle version de l'appex est indésirable, vous vous sentirez profondément violée par l'intolérance éd. De Seventh Edition UNIX (1979). Du manuel :
la source
ex
(je ne connais pas son nom), je pense que les spécifications POSIX sont aussi bonnes que possible. ;) Plus proche de "source originale" à ce stade, même s'il est vrai qu'ils ont commencé comme plus ou moins des descriptions de fonctionnalités existantes.ex
été co-écrit par Bill Joy et Chuck Alley ( web.cecs.pdx.edu/~kirkenda/joy84.html .) Je ne remets pas en question les spécifications POSIX et le fait que lesvi
versions actuelles le suivent, je ne fais que signaler le comportement longtemps le précède.Je ne me souviens d'aucun autre comportement qu'une nouvelle ligne est ajoutée à la fin d'un fichier (utilisation
vi
depuis le milieu des années 80).Le
~
signe qu'une ligne à l'écran qui ne fait pas partie du texte ne signifie pas que le fichier ne se termine pas par une nouvelle ligne. (Il peut être difficile de détecter les erreurs si vous mettez un~
dernier mot de shell dans la dernière ligne). Si vous chargez un fichier court avec une nouvelle ligne à la fin, vous verrez apparaître~
vous - même et réfutez le fait que votre pensée indique un texte ne se terminant pas par une nouvelle ligne.la source
ed
), vous créez des lignes et les modifiez, pas en ajoutant des caractères. J'ai toujours pensé à vi comme éditeur en ligne. Mais je comprends ta surprise.Le texte qui manque de manière incorrecte le saut de ligne ultime dans une
while
boucle de coque entraîne la suppression silencieuse de la dernière ligne.S'assurer qu'il y a une nouvelle ligne ultime est le bon choix, sain et sensé. L'autre option consiste à connaître et à disposer du temps nécessaire pour auditer tout code shell touchant un texte ne disposant pas de saut de ligne ultime, ou risquer de perdre la dernière ligne du texte.
la source