Vi, dosya sonuna sessizce yeni bir satır (LF) ekler mi?


36

Tuhaf bir davranışı anlamakta zorluk çekiyorum: vi, özellikle yazmamış olduğumda, dosyanın sonuna yeni bir satır (ASCII: LF, Unix ( AIX ) sistemi olduğu için) ekliyor gibi görünüyor ).

Dosyayı vi olarak düzenlerim (sonunda yeni bir satır girmemeye dikkat ederek):

# 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.

Vi'nin "olduğu gibi" kaydetmesini bekliyorum, böylece 39 bayt var: ilk üç satırın her birinde 10 ASCII karakter (sayıları 1'den 9'a, ardından yeni bir satır (sistemimde LF)) ve yalnızca 9'undan satır (1'den 9'a kadar olan karakterler, yeni satır / sonlandırıcı yok).

Ama kaydettiğimde 40 bayt (39 yerine) ve od sonlandırıcı bir LF gösteriyor :

# 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?

Dosyayı vi ile yaptıklarımı aynen yapan bir printf ile oluşturursam, beklendiği gibi çalışır:

# ## 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.

Her iki dosya da (foo (40 karakter) ve foo2 (39 karakter) vi ile tekrar açtığımda aynı görünür ...

Ve eğer foo2'yi (39 karakter, sonlandırma yeni satırı yok) vi'de açarsam ve sadece :wqherhangi bir düzenleme yapmadan yaparsam , 40 karakter yazdığını ve satır çekimi ortaya çıktığını söyler!

Daha yeni bir vi'ye erişemiyorum ( bunu AIX, vi ( Vim değil ) sürüm 3.10'da yapıyorum, sanırım? ("-Versiyon" veya bunu bilmenin başka yolları yoktur).

# strings /usr/bin/vi | grep -i 'version.*[0-9]'
@(#) Version 3.10

Bir dosyanın sonuna sessizce yeni bir satır eklemek vi (ve belki de daha yeni sürümde değil mi? Vim?) Normal midir? (Bence ~, önceki satırın yeni satırla bitmediğini belirtti.)

-

Düzenleme: bazı ek güncellemeler ve bir özeti, aşağıdaki cevaplar sayesinde büyük:

  • vi, bulunmayan bir dosyayı yazdığı anda sessizce yeni bir satır ekleyin (dosya boş değilse).

  • bu sadece yazma zamanında yapar! (yani, siz: w'ye kadar: e dosyasını, dosyayı açtığınız gibi hala doğrulamak için kullanabilirsiniz ... (yani: yine de "dosya adı" nı gösterir [Son satır tamamlanmadı] N satırı, M karakteri). Kaydettiğinizde, yeni bir satır belirli bir uyarı vermeden sessizce eklenir (kaç bayt kazandırdığını söyler, ancak bu çoğu durumda yeni bir satır eklendiğini bilmek için yeterli değildir) (benimle ilgili konuştuğunuz için jiliagre sayesinde vi mesajı açarak, değişikliğin gerçekten ne zaman gerçekleştiğini bilmek için bir yol bulmamda bana yardımcı oldu.

  • Bu (sessiz düzeltme) POSIX davranışıdır! (referanslar için @ yalınayak-io cevabına bakınız)


Sadece bütünlüğü için, hangi AIX sürümü (tam sürüm).
EightBitTony

2
Bu seçenek sahip Aix en vi farkında değilim - görünür Vim okunur
Jeff Schaller

1
@JeffSchaller: bağlantı için thx. Ne yazık ki yerli vi ": set noeol" ya da ikili modda açmak için -b seçeneğine sahip değil ...
Olivier Dulac

1
Komutu viçalıştırarak sürümü veya en azından kökeniyle ilgili bir ipucu elde edebilirsiniz :ve.
jlliagre

1
@ThomasDickey Gerçekten. Nedense, IBM komutun normal olarak belgelendiği exkılavuz sayfasını çıkardı :ver.
jlliagre

Yanıtlar:


28

Beklenen vidavranış budur.

Dosyanız tamamlanmamış bir son satıra sahip (yani POSIX standardına göre), bir metin dosyası değil, ikili bir dosya.

vi İkili değil, bir metin dosyası düzenleyicisi olan, kaydettiğinizde incelikle düzeltir.

Bu gibi diğer metin dosyası araçları verir wc, sedve beklenen çıkışı sağlamak sever. Bu vikonuda sessiz olmadığına dikkat edin:


$ printf "one\ntwo" >file     # Create a unterminated file
$ cat file                    # Note the missing newline before the prompt
one
two$ wc -l file               # wc ignores the incomplete last line
       1 file
$ sed '' file > file1
$ cat file1                   # so does a legacy sed
one
$ PATH=$(getconf PATH) sed  '' file
one                           # while a POSIX conformant sed warns you:
sed: Missing newline at end of file file.
two
$ vi file
one
two
~
~
~                             # vi tells you too about the issue
"file" [Incomplete last line] 2 lines, 7 characters

:w

"file" 2 lines, 8 characters  # and tells it writes two lines
                              # You'll even notice it writes one more
                              # character if you are a very shrewd observer :-)
:q
$ cat file                    # the file is now valid text
one
two
$ wc -l file                  # wc reports the expected number of lines
       2 file
$ sed '' file > file1         # sed works as expected
$ cat file1
one
two

Hangi visürümü çalıştırdığınla ilgili bazı ipuçları almak için bu :vekomutu kullanabileceğini not et . Burada burada eski bir SVR4 kullanıyorum, kesinlikle değil vim:

:ve
Version SVR4.0, Solaris 2.5.0

Görünüşe göre seninki şunu yazıyor:

:ve
Version 3.10

Bu muhtemelen vi, AIX'in SVR3 kaynak koduna dayandığı anlamına gelir .

Her durumda, bu davranış ve [Incomplete last line]uyarı mesajı, vien az 1979'dan beri eski Bill Joy'un kaynak kodunda olmuştur ve AFAIK, AIX benzeri tescilli Unix in inşa edildiği System V kaynak kodu bültenlerinden oluşturulan tüm şubelerde tutulmuştur.

Kronolojik olarak konuşursak, bu davranış POSIX uygunluğunun bir sonucu değil, Bill Joy'un sahte metin dosyalarını düzenleyen kullanıcılara yardımcı olma konusundaki orijinal kararının ve on yıl sonra POSIX komitesinin bu toleransı koruma kararının bir sonucudur.

edBunun yerine kullanırsanız vi, eskiden konuyla ilgili daha ayrıntılı olduğunu göreceksiniz, en azından edSVR3 veya daha yeni bir kaynak şubesinden iseniz :

$ ed file
'\n' appended
8
q

Ayrıca, boş bir dosyanın sıfır satır içeren geçerli bir metin dosyası olduğunu unutmayın. Sonrasında düzeltilmesi gereken sonlandırılmış vibir satır olmadığı için, dosyayı kaydederken yeni bir satır eklemiyor.


1
Vi için hata vim'sine inanıyorum;) eski vi, bundan daha az ayrıntılı ...
Olivier Dulac

@OlivierDulac Onları karıştırmıyorum. Bu test, vifarklı bir Unix'te olmasına rağmen, OP'nin yaptığı gibi SVR4 mirası kullanılarak yapıldı . Bu vimya da başka bir klon değil . Cevap bunu netleştirmek için güncellendi.
jlliagre

@ OlivierDulac Hmm, aslında OP olduğunuzu fark ettim. AIX'in viuygulanması için daha eski bir System V dalı kullandığı görülüyor . Muhtemelen SVR3. [Incomplete last line]Dosyayı açtığınızda hiçbir mesaj olmadığından emin misiniz?
jlliagre

@OlivierDulac Bu bağlantı, aynı mesajın AIX viuygulaması tarafından gösterilebileceğini ima ediyor gibi görünüyor : www-01.ibm.com/support/docview.wss?uid=isg1IZ27694
jlliagre

Bunu yarın görmeye çalışacağım
Olivier Dulac

51

POSIX bu davranışı gerektirir, bu nedenle olağandışı bir durum değildir.

Gönderen POSIX manuel vi :

GİRİŞ DOSYALARI

Vi komutu tarafından desteklenen giriş dosyalarının açıklaması için ex komutunun INPUT FILES bölümüne bakın.

POSIX ex el kitabının izini sürdüğünüzde :

GİRİŞ DOSYALARI

Giriş dosyaları, {LINE_MAX} -1 bayttan daha uzun olmayan ve NUL karakteri içermeyen tamamlanmamış bir son satır dışındaki metin dosyaları veya metin dosyaları olacaktır. Varsayılan olarak, eksik olan herhangi bir son satır <son satır> sonundaki gibi işlem görür. Diğer dosya biçimlerinin düzenlenmesine isteğe bağlı olarak eski uygulamalar tarafından izin verilebilir.

Vi kılavuzunun ÇIKIŞ DOSYALARI bölümü ayrıca aşağıdakilere yönlendirilir:

ÇIKIŞ DOSYALARI

Eskiden çıkan çıktı metin dosyaları olacaktır.

Bir çift POSIX tanımı:

3.397 Metin Dosyası

Sıfır veya daha fazla satırda düzenlenmiş karakterleri içeren bir dosya. Satırlar NUL karakteri içermez ve hiçbiri <newline> karakteri dahil olmak üzere {LINE_MAX} bayt uzunluğunu aşamaz. POSIX.1-2008, metin dosyaları ve ikili dosyalar arasında ayrım yapmamasına rağmen (ISO C standardına bakın), birçok yardımcı program metin dosyaları üzerinde çalışırken yalnızca öngörülebilir veya anlamlı çıktılar üretir. Bu tür kısıtlamaları olan standart yardımcı programlar her zaman STDIN veya INPUT FILES bölümlerinde "metin dosyaları" belirtir.

3.206 Satır

Sıfır veya daha fazla <newline> olmayan karakter dizisi artı bir bitiş <newline> karakter.

Bu kılavuz sayfa alıntıları bağlamındaki bu tanımlar, bir uygun ex / vi uygulamasının hatalı bir metin dosyasını kabul etmesi gerektiği halde, eğer o dosyanın yalnızca biçimsizliği eksik bir son satır ise, o dosyanın arabelleğini yazarken sonucun geçerli bir metin dosyası olması gerektiği anlamına gelir.

Bu gönderi POSIX standardının 2013 baskısına atıfta bulunsa da, ilgili hükümler 1997 yılı baskısında da yer almaktadır .

Son olarak, eski hattın newline appriage'sının istenmeyen olduğunu fark ederseniz, Seventh Edition UNIX'in (1979) hoşgörüsüz ed. Kılavuzdan :

Bir dosyayı okurken ed, son satırdan sonra ASCII NUL karakterlerini ve tüm karakterleri atar. ASCII olmayan karakterler içeren dosyaları okumayı reddediyor.


teşekkürler, bu sorumu cevaplıyor. bazı daha iyi cevapların ortaya çıkması durumunda birkaç gün daha bekleyeceğim, ancak şu anda kabul edilen cevap olabileceğinizi düşünüyorum.
Olivier Dulac

Tamamen belgelenmiş cevabı çok iyi bitti, doğrudan özelliklerinden! :)
Wildcard

1
@Wildcard, davranış özellikleri rağmen önceleri.
jlliagre

@jlliagre, Bill Joy’dan veya belki de yaratıcısının ex(ismini bilmediğiniz) bir hatıraınız yoksa , POSIX özelliklerinin beklendiği kadar iyi olduğunu düşünüyorum. ;) Bu noktada “orijinal kaynağa” en yakın olanı, doğru olmasına rağmen, mevcut işlevselliğin az ya da çok tarifi olarak başladılar.
Wildcard

3
@Wildcard exBill Joy ve Chuck Alley tarafından ortaklaşa yazılmıştır ( web.cecs.pdx.edu/~kirkenda/joy84.html .) Ben POSIX özellikleri ve mevcut gerçeği sorgulamıyorum vibültenleri takip etme, sadece davranışı devlet uzun onu yiyor.
jlliagre

1

Bir dosyanın sonuna yeni bir satır eklenecek başka bir davranış hatırlamıyorum ( vi80'li yılların ortasından beri).

~Metnin bir parçası değildir ekranda bir çizgi, dosya yeni bir satır ile bitmiyor değil belirtir. ( ~Kabuk komut dosyalarının son satırına yerleştirirseniz hataları izlemek zorlaşır ). Sonunda yeni bir satır içeren kısa bir dosya yüklerseniz, ~kendinizi görecek ve düşüncenizin yeni satır sonu olmayan bir metni gösterdiğini ispatlayacaksınız.


beni şaşırtan şey, yeni bir hattın eklenmesi ... vi'nin sessizce eklememesini beklemiyorum, ama öyle görünüyor ki ... Bu tutuma ilişkin bir açıklama arıyorum (sorunlu gerçeği: foo2'yi açıyorum (olmadan) sondaki LF) ve sadece: wq, içeriğini değiştirir ... bu yüzden bana bir şey gösterir ama başka bir şeyden tasarruf eder ... garip, en az bir şey söylemek için ^^
Olivier Dulac

selefinde ( ed), satır ekler ve bunları karakter ekleyerek düzenlerdiniz. Ben her zaman vi'yi bir çizgi odaklı editör olarak düşündüm. Ama sürprizini anlıyorum.
Anthon,

1

Bir kabuk whiledöngüsünden geçen son satırdan habersiz olan metin , son satırın sessizce atılmasına neden olur.

$ (echo transaction 1; echo -n transaction 2) \
  | while read line; do echo $line; done
transaction 1
$ 

Nihai bir yeni satır olduğundan emin olmak doğru ve mantıklı ve uygun varsayılandır. Diğer seçenek, nihai satırsonu olmayan metne temas eden tüm kabuk kodlarını denetleme ve zamanı denetleme veya metnin son satırını kaybetme riskini üstlenmeyi içerir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.