Як додати постійні номери рядків до файлу?


22

У мене такий текстовий файл (за допомогою gVim у Windows)

foo bar baz quux 
corge grault garply 
waldo fred plugh 
[...150 more lines...]
xyzzy thud

Я хочу додати число до кожного рядка у файлі. Не використовуючи :set number, а додаючи число як текст, що передує кожному рядку, наступним чином, тому число є частиною файлу.

1. foo bar baz quux 
2. corge grault garply 
3. waldo fred plugh 
[...~150 more lines...]
155. xyzzy thud

awkце, мабуть, інструмент для цієї роботи. Але я на Windows (зітхає).
roblogic

Відповіли тут уже , неважливо :)
roblogic

1
Можливо .. Або це більш загальне?
муру

Це схоже, але я б не знав, що таке постійні номери рядків. По-друге, інше питання стосується всіх рядків (і відповідь це робить) спеціально для gVim для Windows, і це простий нумерований список для одного абзацу лише у простому vim.
kenorb

3
Ну, я думаю, що пост використовує "перманентний", що вказує на те, що буфер повинен бути змінений, і що цифри - це не зовсім візуальна річ (така ж, як ви). Причиною визначення gvim у Windows є уникання зовнішніх утиліт, таких як catабо nl, які можуть робити рядки з номерами, але вони зазвичай не доступні для Windows (як вказує ОП із коментарів про awk). Два найкращих рішення - чистий Vim. Нарешті, всі рядки проти одного пункту - лише питання вибору діапазону. Очевидно, що це не велике питання.
муру

Відповіді:


37

У чистому вигляді Vim:

:%s/^/\=line('.').". "

Пояснення:

:%s/^/            " the substitution will be applied to the beginning of every line
\=                " the rest of the replacement part is an expression
line('.').". "    " the expression returns the current line number concatenated with a dot and a space

Дивіться :help \=і :help line().

Використання виразу в замінній частині дуже потужне і FWIW є досить непоганим пунктом вступу до vimscript.


Як я можу додати цю дуже корисну команду до клавішної карти в vimrc?
cosmicraga

Щоб потрапити на тему довідки vim щодо заміни::help sub-replace-expression
akurtser

9

Одним із приємних речей про макроси Vim є те, що вони можуть повторюватися (вони можуть викликати себе):

  1. Очистити регістр q: qqq
  2. Додайте номер до першого рядка: ggI1.(не забудьте пробіл!)
  3. Поверніться до початку рядка і починайте записувати макрос: 0qq
  4. Скопіюйте номер: yW
  5. Перемістіть рядок вниз і вставте номер: +P
  6. Поверніться до початку рядка і збільште число: 0<c-a>
  7. Поверніться до початку рядка (щоб макрос не зламався, коли він потрапляє до подвійних цифр!): 0
  8. Викличте макрос один раз, щоб зробити його рекурсивним. На даний момент, до сих пір нічого в регістрі д, так що нічого не станеться: @q.
  9. Збережіть макрос: q
  10. Зателефонуйте макросу ще раз і спостерігайте, як іскри літають !: @@

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

Ви можете використовувати рекурсивний макро-трюк для безлічі інших подібних проблем, тому це добре знати.

Якщо ви не хочете використовувати рекурсивний макрос з якихось причин, ви можете пропустити кроки 1 і 8 і використовувати підрахунок, щоб запустити макрос кілька разів, наприклад 100@q, запустить макрос q100 разів.


1
Потужні речі, я кланяюся вашому майстерності. Макроси для мене як чорна магія ...
roblogic

1
@ropata, макрос - це лише послідовність (переважно) команд звичайного режиму.
romainl

1
@romainl Я думаю, що краще вважати це послідовністю натискань клавіш .
Багатий

2
@Rich, це може бути послідовність багатьох речей, включаючи колишні команди.
romainl

2
@romainl Так, тому я вважаю, що найкраще думати про це як натискання клавіш. Він відтворює саме те, що ви вводите на клавіатурі (включаючи, як ви говорите, колишні команди), як якщо б ви все це ввели вручну.
Багатий

7

Мені подобається використовувати глобальну команду vim для виконання таких завдань. Це стосується додавання ітерації до початку рядка або зміни символу в тексті. Це виглядає складніше, ніж інші рішення, але є досить гнучким шаблоном, який можна використовувати, коли вам це зручно, і його легко модифікувати без особливої ​​думки.

Спочатку виберіть діапазон (які рядки ви бажаєте застосувати). Зазвичай я використовую позначки (наприклад, maна першому рядку та mbв другому, але ви також можете використовувати номери рядків або візуальний вибір), а потім вводите модифікацію наступної команди (наразі налаштована для вашого випадку використання)

:let i=1|'a,'bg/^/s/^/\=i.". "/|let i=i+1

Деконструкція

:let i=1

Це встановлює змінну iзі початковим значенням. Зазвичай списки починаються з 1, тому я встановлюю i на 1.

|

На панелі запускається нова команда

'a,'b

Це встановлює діапазон наступної команди. Я переходжу від позначки aдо позначки b, яка буде встановлена ​​в першому та останньому рядку вашого списку.

g/^/

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

Item some txt
other text

Item second item
whatever
Item third

і потрібно лише поставити ці мітки перед Itemі проігнорувати інші рядки, зробіть g/Item/або g/^Item/замість цього (припускаючи буквальний текст елемента)

s/^/\=i.". "/

Це виконує регулярний вираз, щоб замінити початок рядка значенням iоб'єднаного з a .. Як правило, ви можете це робити будь-що (замініть ярлик Itemцифрою, наприклад).

|let i=i+1

Незважаючи на те, що панель запускає нову команду, вона встановлює другу команду, яку слід запускати в межах глобальної команди, а не після того, як глобальна буде завершена. Результат - приріст, iперш ніж наступний рядок буде оброблений g. Тут є ще одне місце гнучкості. Модифікація i може бути будь-якою (приріст на 2, виклик функції, яка генерує наступний елемент послідовності Фібоначчі, як би там не було).


7

Додайте числа до всіх рядків

Можна використовувати :%!nl -baабо :%!cat -nкоманди, які додадуть номери рядків до всіх рядків.

У Windows вам потрібно встановити Cygwin / MSYS / SUA.

Додайте числа до вибраних рядків

Щоб додати номери лише для вибраних рядків, будь ласка, виберіть їх у візуальному режимі ( vта курсори), потім, коли закінчите, виконайте команду: :%!nl(ігноруйте порожні рядки) або :%!cat -n(пусті рядки включені).

Форматування

Щоб видалити зайві пробіли, виберіть їх у візуальному блоці ( Ctrl+ v) та видаліть їх ( x).

Для того, щоб додати деякі символи ( ., :, )) після цифр, виберіть їх у візуальному блоці ( Ctrl+ v), потім додати символ ( Aвведіть символ, а потім закінчити з Esc).


2
Це не дає того самого форматування, як зазначено в питанні. Однак мені подобається простота рішення.
Карл Інгве Лервег

@ KarlYngveLervåg Спасибі, включив це у відповідь.
kenorb

5

Модифікація відповіді romainl :

:%s/^\(\d\+\. \)\?/\=line('.').". "

Це не просто додасть номери рядків, але й замінить вихідні номери рядків, які вони вже є. З іншого боку, якщо ви вставили рядок посередині, він перенумерує все, як очікувалося.

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

Додана частина:

  • ^ - Початок рядка
  • \( - Запуск нової підгрупи
  • \d\+ - Зіставити цифру раз чи більше
  • \. - Зіставити крапку ( .) та пробіл .
  • \) - Кінцева підгрупа
  • \? - Зробіть групу необов’язковою, щоб вона працювала як раніше, якщо в цьому рядку ще немає номера.

Підказка про бонус:
Щоб видалити номери рядків, ви можете використовувати ту саму схему з порожньою частиною repalce:

:%s/^\(\d\+\. \)\?//

5
I1. <esc>^qqyWjP^<C-a>q

Це номери перших двох рядків, і ви можете натиснути @qдля нумерації наступних рядків (або введіть, наприклад, 18@qякщо ви хочете набрати 20 рядків).

Пояснення:

I1. <esc>  Number the first line
hqq        Go back to the start of the line and start recording a macro
yWjP       Copy the line number to the next line
^<C-a>     Increment the next line's line number
q          Finish recording

Перевага цього в тому, що він не вимагає ніяких зовнішніх команд, що корисно, наприклад, якщо ви працюєте з Vim в Windows.


Після введення 1. <esc>hви перебуваєте на другому, а не на першому стовпці. Я хотів би замінити hз 0, після чого я думаю , що ваше рішення має бути дуже хорошим.
Карл Інгве Лервег

@ KarlYngveLervåg Уопс, це був друкарський помилок. Спасибі, виправили.
Doorknob

Без проблем. Однак ви досі не оновлювали пояснення. Також: На багатьох клавіатурах ^чекає другого символу, щоб дозволити вводити комбінації типу ^a -> â. Я все ще погоджуюся з найкращим рішенням, але я думаю, що це слід також згадати.
Карл Інгве Лервег

3

Я вважаю, що обрана відповідь найкраща, але, маючи на увазі різноманітність, я запропоную альтернативу за допомогою зовнішньої програми:

:%!cat -n

Це дозволить фільтрувати весь ваш буфер (як позначається %) через зовнішню програму cat, де -nпрапор попередньо містить кожен рядок введення з номером рядка.

Це, звичайно, вимагає, щоб ви catвстановили, що справедливо для (можливо) всіх Unix-подібних систем.

Дізнайтеся :help :range!більше про фільтрацію через зовнішні програми.


1
Я розумію, що аскер використовує gVim у Windows, тому це рішення, ймовірно, там не працюватиме. Однак я думаю, що це все ж дає певну можливість іншим навчитися на цьому.
tommcdo

Якщо ви встановили msysgitта додали це до свого PATH (IIRC - це опція встановлення), це рішення також має працювати в Windows.
Мартін Турноїй

4
cat -nне є POSIX, але nlє, тому це може бути кращим варіантом.
муру

2

Трохи хакістим рішенням може бути наступне (все написане між <і> потрібно вставити після натискання Ctrl + v):

:%normal :redir @"<Enter>:-=<Enter>:redir END<Enter>I<C-R>".<Tab><Esc>kdd

Деконструкція

:%normal {commands}

виконує команду звичайного режиму в кожному рядку, визначеному діапазоном, в цьому випадку в кожному рядку

:redir @"

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

:.=

- це команда ex, яка виводить номер поточного рядка (на жаль, з попереднього нового рядка)

:redir END

зупиняє переадресацію на неназваний буфер

I<C-R>".<Tab><Esc>

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

kdd

йде один рядок вгору і видаляє новий рядок, який є результатом команди:. =

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.