Mam problem ze zrozumieniem dziwnego zachowania: vi wydaje się dodawać nową linię (ASCII: LF, ponieważ jest to system uniksowy ( AIX )) na końcu pliku, kiedy NIE specjalnie go wpisałem.
Plik jako taki edytuję w vi (uważając, aby nie wprowadzić nowego wiersza na końcu):
# 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.
Spodziewam się, że vi zapisze go „tak, jak jest”, więc powinien mieć 39 bajtów: 10 znaków ASCII w każdym z pierwszych trzech wierszy (cyfry od 1 do 9, po których następuje nowa linia (LF w moim systemie)) i tylko 9 w ostatnim linia (znaki od 1 do 9, bez kończącej nowej linii / LF).
Ale pojawia się, kiedy go zapisuję, ma 40 bajtów (zamiast 39), a od pokazuje końcowy LF :
# 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?
Jeśli utworzę plik z printf, który robi dokładnie to, co zrobiłem w vi, działa zgodnie z oczekiwaniami:
# ## 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.
Oba pliki (foo (40 znaków) i foo2 (39 znaków) wyglądają dokładnie tak samo, jeśli ponownie je otworzę za pomocą vi ...
A jeśli otworzę foo2 (39 znaków, bez kończącego nowego wiersza) w vi i po prostu zrobię to :wq
bez edycji, to napisa , że zapisuje 40 znaków, i pojawia się wiersz!
Nie mogę uzyskać dostępu do nowszej wersji vi (robię to w systemie AIX, vi (nie w Vimie ) w wersji 3.10? Myślę, że (brak „-wersji” lub innych sposobów jej poznania)).
# strings /usr/bin/vi | grep -i 'version.*[0-9]'
@(#) Version 3.10
Czy to normalne, że vi (a może nie w nowszej wersji? Lub Vim?) Cicho dodaje nowy wiersz na końcu pliku? (Myślałem, że ~ wskazuje, że poprzednia linia NIE kończyła się nową linią).
-
Edycja: kilka dodatkowych aktualizacji i trochę podsumowania, wielkie dzięki poniższym odpowiedziom:
vi cicho dodaje końcowy znak nowej linii w momencie, gdy zapisuje plik, który go nie ma (chyba że plik jest pusty).
robi to tylko w momencie pisania! (tzn. dopóki nie w: możesz użyć: e, aby sprawdzić, czy plik jest nadal otwarty, gdy go otworzyłeś ... (tj .: nadal pokazuje „nazwę pliku” [ostatnia linia nie jest kompletna] N linia, znak M). Kiedy zapisujesz, nowy wiersz jest dodawany w trybie cichym, bez specjalnego ostrzeżenia (mówi, ile bajtów zapisuje, ale w większości przypadków to nie wystarczy, aby wiedzieć, że dodano nowy wiersz) (dzięki @jiliagre za rozmowę ze mną o otwierając komunikat vi, pomógł mi znaleźć sposób, aby wiedzieć, kiedy zmiana rzeczywiście nastąpi)
To (cicha korekta) jest zachowaniem POSIX ! (patrz odniesienia @ odpowiedź boso-io)
vi
wersję lub przynajmniej wskazówkę dotyczącą jej pochodzenia, uruchamiając:ve
polecenie.ex
stronę podręcznika, na której:ver
polecenie jest zwykle dokumentowane.Odpowiedzi:
To jest oczekiwane
vi
zachowanie.Twój plik ma niekompletny ostatni wiersz, więc ściśle mówiąc (tj. Zgodnie ze standardem POSIX), nie jest to plik tekstowy, ale plik binarny.
vi
który jest edytorem plików tekstowych, a nie binarnym, z wdziękiem naprawia go podczas zapisywania.Pozwala to innym narzędziom plików tekstowych, takim jak i podobnym
wc
,sed
zapewnić oczekiwany wynik. Pamiętaj, żevi
nie milczy na ten temat:Uwaga: aby uzyskać wskazówki dotyczące
vi
używanej wersji, możesz użyć:ve
polecenia. To pokazuje, że tutaj używam starszego SVR4, zdecydowanie nievim
:Najwyraźniej twój twierdzi:
To prawdopodobnie oznacza, że AIX
vi
jest oparty na kodzie źródłowym SVR3.W każdym razie takie zachowanie i
[Incomplete last line]
komunikat ostrzegawczy znajdują się w starszymvi
kodzie źródłowym Billa Joya od co najmniej 1979 r. I AFAIK, zachowane we wszystkich gałęziach utworzonych z wersji kodu źródłowego Systemu V, z których zbudowano zastrzeżony system uniksowy, taki jak AIX.Chronologicznie rzecz biorąc, takie zachowanie nie jest zatem konsekwencją zgodności z POSIX, ale bardziej konsekwencją pierwotnej decyzji Billa Joya o pomocy użytkownikom w edytowaniu fałszywych plików tekstowych, a następnie, dekadę później, decyzji komitetu POSIX o zachowaniu tej tolerancji.
Jeśli użyjesz
ed
zamiastvi
, zauważysz, że ten pierwszy jest bardziej szczegółowy w kwestii, przynajmniej jeślied
pochodzi z SVR3 lub nowszej gałęzi źródłowej:Zauważ też, że pusty plik jest prawidłowym plikiem tekstowym, który zawiera zero linii. Ponieważ nie ma wtedy niezakończonej linii do naprawienia,
vi
nie dołącza nowej linii podczas zapisywania pliku.źródło
vi
podobnie jak OP, chociaż na innym Uniksie. To nie jestvim
ani inny klon. Odpowiedź zaktualizowana w celu wyjaśnienia tego.vi
implementacji starszej gałęzi System V. Prawdopodobnie SVR3. Czy na pewno nie ma[Incomplete last line]
wiadomości po otwarciu pliku?vi
implementację systemu AIX : www-01.ibm.com/support/docview.wss?uid=isg1IZ27694POSIX wymaga takiego zachowania, więc nie jest to w żaden sposób niezwykłe.
Z podręcznika POSIX vi :
Podążając ścieżką do instrukcji POSIX ex :
Sekcja PLIKI WYJŚCIOWE w podręczniku vi również przekierowuje do np .:
Para definicji POSIX:
Te definicje w kontekście tych fragmentów strony podręcznika oznaczają, że chociaż zgodna implementacja ex / vi musi zaakceptować zniekształcony plik tekstowy, jeśli jedyną deformacją tego pliku jest nieobecna końcowa nowa linia, podczas zapisywania bufora tego pliku wynik musi być poprawnym plikiem tekstowym.
Chociaż ten post odnosi się do wydania standardu POSIX 2013, odpowiednie postanowienia pojawiają się również w znacznie starszym wydaniu z 1997 roku .
Na koniec, jeśli uznasz, że nowa wersja eks byłaby niepożądana, poczujesz się głęboko naruszony przez nietolerancyjną edycję Seventh Edition UNIX (1979). Z instrukcji :
źródło
ex
(nie znam jego imienia), myślę, że specyfikacje POSIX są tak dobre, jak można się spodziewać. ;) W tym momencie najbliższy „oryginalnemu źródłu”, chociaż to prawda, że zaczęli jako mniej więcej opisy istniejącej funkcjonalności.ex
został napisany wspólnie przez Billa Joya i Chucka Alleya ( web.cecs.pdx.edu/~kirkenda/joy84.html .) Nie kwestionuję specyfikacji POSIX i fakt, że obecnevi
wersje ją śledzą, po prostu stwierdzam zachowanie długo to poprzedza.Nie przypominam sobie żadnego innego zachowania, które dodaje się nową linię na końcu pliku (używając
vi
od połowy lat 80.).~
Wskazuje, że linia na ekranie, który nie jest częścią tekstu, a nie, że plik nie kończy się w nowej linii. (Śledzenie błędów może być trudne, jeśli umieścisz~
w ostatnim wierszu skryptów powłoki). Jeśli załadujesz krótki plik z nową linią na końcu, zobaczysz~
siebie i obalisz się, że twoja myśl wskazuje, że tekst nie kończy nowej linii.źródło
ed
) można było tworzyć linie i edytować je, nie dodając znaków. Zawsze myślałem o vi jako edytorze zorientowanym liniowo. Ale rozumiem twoją niespodziankę.Tekst niepoprawnie pozbawiony ostatecznego nowego wiersza przebiegającego przez
while
pętlę powłoki powoduje, że ostatni wiersz jest dyskretnie odrzucany.Zapewnienie ostatecznej nowej linii jest właściwym, rozsądnym i właściwym domyślnym. Inna opcja obejmuje znajomość i czas na sprawdzenie całego kodu powłoki, który dotyka tekstu bez ostatecznego nowego wiersza, lub ryzykuje utratę ostatniej linii tekstu.
źródło