Чому Vim додає новий рядок? Це конвенція?


22

Якщо я відкрию Vim і введіть, itest<Esc>:wqто я отримаю файл, у якому немає нових рядків у Vim, але, схоже, є новий рядок у коді:

$ vim -u NONE test.txt
$ cat test.txt | hd
00000000  74 65 73 74 0a                    |test.|
00000005

Якщо я відкрию Vim і введіть, itest<Return><Esc>:wqя отримаю файл, який має один новий рядок у Vim, але два нові рядки в коді:

$ rm test.txt
$ vim -u NONE test.txt
$ cat test.txt | hd
00000000  74 65 73 74 0a 0a                 |test..|
00000006

Зауважте, що я відкриваю Vim, -u NONEтому локальна конфігурація не використовується. Зауважте також, що це може бути пов'язане з попереднім моїм питанням .

Це моя інформація про систему:

$ uname -a
Linux awsAlpha 3.2.0-60-virtual #91-Ubuntu SMP Wed Feb 19 04:13:28 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ vim --version
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled May  4 2012 04:25:35)
Included patches: 1-429
Modified by pkg-vim-maintainers@lists.alioth.debian.org
Compiled by buildd@

Я можу підтвердити точно таку ж поведінку в цій системі:

$ uname -a
Linux bruno 3.5.0-48-generic #72-Ubuntu SMP Mon Mar 10 23:18:29 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
$ vim --version
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Oct 26 2012 16:45:33)
Included patches: 1-547
Modified by pkg-vim-maintainers@lists.alioth.debian.org
Compiled by buildd@

Чому Vim додає новий рядок? Це конвенція?

Ось декілька роз'яснень щодо hdкоманди, встановленої на сервері Ubuntu:

$ man hd | head -4
HEXDUMP(1)            BSD General Commands Manual            HEXDUMP(1)

NAME
     hexdump, hd — ASCII, decimal, hexadecimal, octal dump

8
Здається, це конвенція. Ось як її відключити, якщо хочете. Ось історія цього.
jliv902

Відповіді:


28

Конвенція для текстових файлів Unix полягає в тому, що кожен рядок закінчується новим рядком і що нові рядки є термінаторами рядків, а не роздільниками рядків.

Коли Vim зберігає буфер як файл, він закінчує кожен рядок послідовністю кінця рядка для цього формату файлу, який для Unix є новим рядком. Побачити

:help 'fileformat'

Якщо ви використовуєте інструменти для обробки тексту Unix, найкраще дотримуватися цієї конвенції. Однак якщо у вас є потреба не ставити новий рядок наприкінці останнього рядка файлу, ви можете це зробити. Vim вважає такі файли "бінарними". Побачити

:help 'binary'
:help edit-binary

1
о, це цікаво. Тож окрім відомого \ r \ n vs \ n. Windows використовує роздільники ліній, а unix використовує лінійні термінатори? і це документально десь задокументовано? Я знаю, що тут визначено, що, мабуть, застосовується до unix "ISO / IEC 9899: 2011, розділ §7.21.2. Потоки говорить: Текстовий потік - це впорядкована послідовність символів, складена у рядки, кожен рядок складається з нуля чи більше символів плюс завершальний новий -лінійний персонаж »
барлоп

але де задокументовано, що Windows використовує роздільник ліній?
барлоп

2

Vim не додає нічого, чого ви там самі не помістили.

Символ "нового рядка" не є "новим рядком", і обидва приклади є абсолютно нормальними:

  • у першому файл містить лише один рядок, щоб ви отримали один символ "нового рядка",
  • у другому файл містить два рядки, щоб ви отримали два символи "нового рядка".

2
Це дійсно додає новий рядок. Перевірте його наступним чином: printf "\x41" > /tmp/test.txtпотім перевірте, чи має він єдиний символ "A" xxd /tmp/test.txt. Тепер vim /tmp/test.txt<ENTER>:wq. Перевірте ще раз, щоб побачити файл з двома байтами: 'A \ n'.
Руслан

Рядки закінчуються символом нового рядка. У вас є один рядок, таким чином, ви маєте один символ нового рядка.
romainl

Ну, адже printfтут у мене не було чітко сформованих «ліній». Після vim у мене є. Отже, це додає щось таке, чого я туди не поклав.
Руслан

Те, що ви printfне є рядком, якщо ви не додасте \n. Будучи текстовим редактором, Vim займається рядками за замовчуванням, і будь-який текст, який ви вставляєте у файл, є , принаймні, рядком, якщо ви прямо не скажете Vim цього не робити.
romainl

2

Невиправлені текстові файли є злісними з кількох причин; ось я ще не бачив згадки:

У гіпотетичному світі, де текстові файли без зворотного нового рядка є прийнятними, не було б різниці між файлом, що містить 0 рядків, і файлом, що містить 1 порожній рядок. Обидва вони були представлені 0-байтовим файлом.

Неможливо визначити, скільки рядків у файлі було б погано.


Текстові файли в системах, що не входять до Unix, містять нуль або більше повних рядків, плюс неповний рядок із нулем або більше символів. Порожній файл не містить порожнього рядка; він містить нуль повних рядків і частковий рядок нульових символів. Де двозначність?
supercat

Ця "часткова лінія" - неприємне поняття. Ви не можете мати його ніде, крім кінця файлу, і ви не можете створити файл, який не має "часткової лінії". Це додає більше розбиття до конкатенації файлів - навіть якщо ви вставляєте новий рядок між файлами, ви отримуєте щось, що не є семантично еквівалентним оригінальній парі файлів (тому що з 2-х файлів у вас було 2 часткові рядки, і один з них став чимось різні.) Неелегантна пропозиція.

Те, що об'єднання файлів призведе до того, що будь-який частковий рядок в кінці першого буде попередньо поданий до наступного файлу, як правило, хиткий у випадках, коли обидва файли містять повні рядки (іноді може бути корисно об'єднати файли, які не містять жодних повних рядків ), але це те, що воно є. Unix не забороняє побудову текстових файлів, що закінчуються частковими рядками, і я вважаю, що об'єднання таких файлів буде вести себе як у MSDOS. Думаю, різниця полягає в тому, що багато редакторів на базі DOS історично вважали, що завантаження та негайне збереження файлу повинно отримати новий файл ...
supercat

... який є бітовим ідентичним старій (зареєстрованим користувачам ранніх версій PC-Write було доручено використовувати його для відкриття копії виконуваного файлу, переходу в режим перезапису, пошуку певного рядка та заміни його на свій серійний номер!). Примушування файлів закінчуватися новими рядками при їх збереженні порушить це обмеження.
supercat

2

Тепер Vim 8.0 передбачає це за допомогою fixeolопції. Зокрема, якщо ви робите:

:set nofixeol

тоді Vim не додасть символу нової лінії в кінці остаточного рядка, якщо у файлу його ще не було.

Це може входити у плагін файлів, а можливо навіть у ваш .vimrc.

(Це вдосконалення, :set binaryоскільки воно впливає лише на остаточний характер розриву рядків, тоді як binaryтакож змінюється купа інших форм поведінки, яких ви, мабуть, не хочете, якщо ви фактично не редагуєте двійковий файл.)

Нещодавно створений файл матиме за замовчуванням символ переривання рядків. Ви можете змінити це (і переключити файл, у якого вже є остаточний новий рядок, на такий, що не має), виконавши:

:set noeol

Це потрібно встановити спеціально для кожного файлу, який ви бажаєте змінити: завантаження файлу в буфер завжди встановлюватиметься eolвідповідно до поточного стану файлу.


1

За допомогою команди 'j' ви можете з'єднати всі рядки в один.

Якщо ви також хочете видалити LF або CRLF в останньому рядку, виконайте наступне в vi.

$ vi file
:set binary
:set noeol
:w!
:f          look for [noeol] on the status line
:q
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.