Saya mengalami kesulitan memahami perilaku aneh: vi tampaknya menambahkan baris baru (ASCII: LF, karena ini adalah sistem Unix ( AIX )) di akhir file, ketika saya TIDAK secara spesifik mengetiknya.
Saya mengedit file seperti itu di vi (berhati-hati untuk tidak memasukkan baris baru di akhir):
# 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.
Saya berharap vi untuk menyimpannya "sebagaimana adanya", sehingga memiliki 39 byte: 10 karakter ASCII pada masing-masing dari tiga baris pertama (angka 1 hingga 9, diikuti oleh baris baru (LF pada sistem saya)) dan hanya 9 pada yang terakhir baris (karakter 1 hingga 9, tidak ada penghentian baris baru / LF).
Tapi itu muncul ketika saya menyimpannya 40 byte (bukan 39), dan od menunjukkan LF terminating :
# 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?
Jika saya membuat file dengan printf melakukan apa yang saya lakukan di dalam vi, itu berfungsi seperti yang diharapkan:
# ## 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.
Kedua file (foo (40 karakter) dan foo2 (39 karakter) tampak persis sama jika saya membukanya kembali dengan ...
Dan jika saya membuka foo2 (39 karakter, tidak ada penghentian baris baru) di vi dan hanya melakukan :wq
tanpa mengeditnya , ia mengatakan itu menulis 40 karakter, dan linefeed muncul!
Saya tidak dapat memiliki akses ke vi yang lebih baru (saya melakukan ini pada AIX, vi (bukan Vim ) versi 3.10 saya pikir? (Tidak ada "-versi" atau cara lain untuk mengetahuinya)).
# strings /usr/bin/vi | grep -i 'version.*[0-9]'
@(#) Version 3.10
Apakah normal untuk vi (dan mungkin tidak dalam versi yang lebih baru? Atau Vim?) Untuk menambahkan baris baru secara diam-diam di akhir file? (Saya pikir ~ mengindikasikan bahwa baris sebelumnya TIDAK diakhiri dengan baris baru.)
-
Sunting: beberapa pembaruan tambahan dan sedikit ringkasan, dengan banyak terima kasih atas jawaban di bawah ini:
vi secara diam-diam menambahkan baris baru pada saat itu menulis file yang tidak memilikinya (kecuali file kosong).
itu hanya terjadi pada saat penulisan! (yaitu, sampai Anda: w, Anda dapat menggunakan: e untuk memverifikasi bahwa file tersebut masih saat Anda membukanya ... (yaitu: itu masih menunjukkan "nama file" [Baris terakhir tidak lengkap] N baris, karakter M). Ketika Anda menyimpan, baris baru ditambahkan secara diam-diam, tanpa peringatan khusus (ia mengatakan berapa banyak byte yang disimpannya, tetapi dalam kebanyakan kasus tidak cukup untuk mengetahui baris baru ditambahkan) (terima kasih kepada @jiliagre karena berbicara dengan saya tentang membuka pesan vi, itu membantu saya menemukan cara untuk mengetahui kapan perubahan itu benar-benar terjadi)
Ini (koreksi diam-diam) adalah perilaku POSIX ! (lihat jawaban @ barefoot-io untuk referensi)
vi
versi atau setidaknya petunjuk tentang asalnya dengan menjalankan:ve
perintah.ex
halaman buku panduan tempat:ver
perintah biasanya didokumentasikan.Jawaban:
Inilah
vi
perilaku yang diharapkan .File Anda memiliki baris terakhir yang tidak lengkap sehingga benar-benar berbicara (yaitu sesuai dengan standar POSIX), itu bukan file teks tetapi file biner.
vi
yang merupakan editor file teks, bukan biner, memperbaikinya dengan anggun saat Anda menyimpannya.Ini memungkinkan alat file teks lain suka
wc
,sed
dan suka untuk memberikan hasil yang diharapkan. Perhatikan bahwavi
tidak ada masalah tentang masalah ini:Catatan, untuk mendapatkan beberapa petunjuk tentang
vi
versi apa yang Anda jalankan, Anda dapat menggunakan:ve
perintah. Ini menunjukkan di sini saya menggunakan satu warisan SVR4 di sini, pasti tidakvim
:Rupanya, milik Anda menyatakan:
Itu kemungkinan berarti AIX
vi
didasarkan pada kode sumber SVR3.Bagaimanapun, perilaku ini, dan
[Incomplete last line]
pesan peringatan telah ada dalamvi
kode sumber warisan Bill Joy sejak setidaknya 1979 dan AFAIK, dipertahankan di semua cabang yang dibuat dari rilis kode sumber Sistem V, dari mana Unix yang dipatenkan seperti AIX dibuat.Berbicara secara kronologis, perilaku ini kemudian bukan konsekuensi dari kesesuaian POSIX tetapi lebih merupakan konsekuensi dari keputusan awal Bill Joy untuk membantu pengguna mengedit file teks palsu, dan kemudian, satu dekade kemudian, komite POSIX memutuskan untuk mempertahankan toleransi ini.
Jika Anda menggunakan
ed
alih-alihvi
, Anda akan melihat bahwa yang pertama lebih bertele-tele tentang masalah ini, setidaknya jika Andaed
berasal dari SVR3 atau cabang sumber yang lebih baru:Perhatikan juga bahwa file kosong adalah file teks yang valid yang berisi garis nol. Karena tidak ada baris yang tidak ditentukan untuk diperbaiki,
vi
tidak menambahkan baris baru saat menyimpan file.sumber
vi
seperti halnya OP, meskipun pada Unix yang berbeda. Ini bukanvim
atau klon lain. Jawaban diperbarui untuk memperjelas ini.vi
implementasinya. Mungkin SVR3. Apakah Anda yakin tidak ada[Incomplete last line]
pesan saat Anda membuka file?vi
implementasi AIX : www-01.ibm.com/support/docview.wss?uid=isg1IZ27694POSIX membutuhkan perilaku ini, jadi tidak aneh.
Dari manual POSIX vi :
Mengikuti jejak ke manual ex POSIX :
Bagian OUTPUT FILES dari manual vi juga mengarahkan ke ex:
Sepasang definisi POSIX:
Definisi-definisi ini dalam konteks kutipan halaman buku panduan ini berarti bahwa sementara implementasi ex / konforman harus menerima file teks yang salah jika hanya deformitas file tersebut merupakan baris akhir yang tidak ada, ketika menulis buffer file tersebut hasilnya harus berupa file teks yang valid.
Sementara posting ini telah merujuk pada edisi 2013 dari standar POSIX, ketentuan yang relevan juga muncul dalam edisi 1997 yang jauh lebih tua .
Terakhir, jika Anda menemukan bahwa penayangan iklan baris baru mantan tidak diterima, Anda akan merasa sangat dilanggar oleh Seventh Edition UNIX's (1979) intolerant ed. Dari manual :
sumber
ex
(tidak tahu namanya), saya pikir spesifikasi POSIX sebagus yang bisa diharapkan. ;) Paling dekat dengan "sumber asli" pada titik ini, meskipun memang benar mereka mulai lebih atau kurang sebagai deskripsi fungsi yang ada.ex
ditulis bersama oleh Bill Joy dan Chuck Alley ( web.cecs.pdx.edu/~kirkenda/joy84.html .) Saya tidak mempertanyakan spesifikasi POSIX dan faktavi
rilis saat ini memang mengikutinya, saya hanya menyatakan perilakunya lama sebelum itu.Saya tidak ingat perilaku lain yang ditambahkan baris baru di akhir file (menggunakan
vi
sejak pertengahan 80-an).The
~
menunjukkan bahwa garis di layar yang bukan bagian dari teks, bukan bahwa file tersebut tidak berakhir di baris baru. (Anda bisa mendapatkan kesulitan untuk melacak kesalahan jika Anda menempatkan~
pada baris terakhir skrip shell). Jika Anda memuat file pendek dengan baris baru di akhir, Anda akan melihat~
sendiri dan menyangkal bahwa menurut Anda itu menunjukkan teks yang tidak diakhiri baris baru.sumber
ed
) Anda akan membuat garis dan mengeditnya, bukan dengan menambahkan karakter. Saya selalu berpikir tentang vi sebagai editor berorientasi garis juga. Tapi aku mengerti keterkejutanmu.Teks yang tidak memiliki baris baris terakhir yang dijalankan melalui shell
while
loop akan mengakibatkan baris terakhir dibuang secara diam-diam.Memastikan bahwa ada baris baru utama adalah standar yang benar dan waras dan tepat. Opsi lainnya melibatkan mengetahui dan memiliki waktu untuk mengaudit semua kode shell yang menyentuh teks yang tidak memiliki baris akhir, atau mengambil risiko kehilangan baris terakhir teks.
sumber