Как сгенерировать числовую последовательность в файле с помощью vi или Vim?

Есть ли способ сгенерировать числовую последовательность в vi или Vim?

Например, для произвольного диапазона строк от i до j (где i ‹ j) в открытом файле в Vim есть способ сгенерировать числовую последовательность от числа 1 в строке i до номера (j − i + 1 ) в строке j?

Скажем, у меня есть следующие строки в файле:

this is line #1
this is line #2
this is line #3
this is line #4
this is line #5
this is line #6
this is line #7
this is line #8
this is line #9
this is line #10

Я хочу дополнить числовую последовательность от строки 4 до строки 8 цифрами от 1 до 5. После операции результирующий файл должен выглядеть следующим образом:

this is line #1
this is line #2
this is line #3
1 this is line #4
2 this is line #5
3 this is line #6
4 this is line #7
5 this is line #8
this is line #9
this is line #10

Если это возможно, есть ли способ использовать разные размеры шагов для сгенерированной последовательности? Например, можно ли вместо размера шага использовать 2, чтобы результирующая последовательность была 2, 4, 6, 8 и т. д.?

Примечание. Вопрос «как добавить номера строк в диапазон строк в Vim?»» поднимает похожую проблему, но это не то же самое.


person Sangeeth Saravanaraj    schedule 28.03.2012    source источник
comment
Этот плагин не является полным решением вашей проблемы, но он чрезвычайно полезен для добавления столбцов чисел: VisIncr. Документы здесь. ПОМОЩЬ.   -  person lcd047    schedule 30.04.2015


Ответы (10)


Выделите несколько строк с помощью V (Shift-v), затем введите команду ниже:

:let i=1 | '<,'>g/^/ s//\=i . " "/ | let i+=2

Введите :help sub-replace-expression, чтобы узнать больше.

person kev    schedule 28.03.2012
comment
Спасибо за это! Вим такой мощный!! Попробуйте это: :let i=1 | let j=1 | '<,'>g/^/ s//\=i/ | let c=i+j | let j=i | let i=c - person while; 03.10.2013
comment
Кто-нибудь может это объяснить? - person Jin; 29.01.2015
comment
@Jin Проверьте этот пост на g stackoverflow.com/questions/28403622/ Покажите мне, если вам нужна дополнительная подсказка. - person George; 09.02.2015
comment
Что если я хочу, чтобы номер префикса был дополнен нулями? - person hippietrail; 29.04.2015
comment
Когда я пробую это на Vim 7.4 в Windows 7, я получаю E481: No range allowed - person hippietrail; 29.04.2015
comment
Чтобы связать это с клавишей, сначала создайте функцию. Не используйте ключевое слово range (как я), чтобы применить его только один раз ко всем строкам: function! NumberedList() range :let i=1 | '<,'>g/^/ s//\=i . ". "/ | let i+=1 endfunction А затем привязать его к ключу в визуальном режиме vnoremap <Leader>nl :call NumberedList()<CR>. Я добавил точку после каждой цифры, чтобы создать нумерованный список. - person joelostblom; 23.09.2016
comment
@hippietrail в визуальном режиме Vim автоматически добавит перед следующей командой визуальный диапазон '<,'>, когда вы нажмете :, а в данном случае это не то, что вам нужно. Введите CTRL-U после :, чтобы очистить командную строку, а затем введите команду еще раз. - person gbs; 02.12.2016

Начиная с Vim 7.4.754 можно использовать g Ctrl-a, см. :help v_g_CTRL-A

Перейдите к строке #4, используйте Ctrl-v, чтобы выделить первый символ по блокам, спуститесь на 4 строки вниз, нажмите Shift i, введите 0 (это 0< /kbd>, затем Пробел) и Esc для выхода из режима вставки.

Теперь используйте gv, чтобы повторно выбрать ранее выбранную область. Нажмите g Ctrl-a, чтобы создать последовательность.

Я начинаю здесь с 0, поэтому я могу повторно выбрать gv. Если вы начинаете с 1, вам нужно повторно выбрать вручную, опуская первый 1.

Используйте 2g Ctrl-a, чтобы использовать количество шагов, равное 2.


снимок экрана, демонстрирующий создание числовой последовательности

person rkta    schedule 23.01.2018
comment
Замечательно. После 20 лет использования Vim я до сих пор поражаюсь его возможностям. - person Joseph Paul; 15.12.2019
comment
Вы использовали плагин или какой-то трюк, чтобы отображался текст каждого нажатия клавиши, когда вы делали этот анимированный gif? - person slm; 03.02.2020
comment
Инструмент называется screenkey и его можно найти на gitlab. - person rkta; 17.10.2020
comment
У меня не работало ни на gvim, ни на vim. Вот решение, которое сработало для меня vim.fandom.com/wiki/Increasing_or_decreasing_numbers. Например. qa Y p Ctrl-A q 5@a - person syam; 13.03.2021
comment
@syam Интересно, не могли бы вы поделиться выводом vim --version? - person rkta; 13.03.2021

Вместо сложной конструкции вы можете просто использовать макрос с функцией CTRL-a для увеличения начального числа. Пример данных:

aaa
bbb
ccc

сначала вставьте начальный номер и пробел:

1 aaa
bbb
ccc

затем запишите этот макрос в строке 1 (<C-a> означает нажмите CTRL-a):

qq0yf 0j0P0<C-a>q

Объяснение:

  1. qq: записать макрос в регистр q
  2. 0: перейти к первому столбцу.
  3. yf: скопировать все до первого пробела включительно (помните, что в первой строке есть 1 и пробел).
  4. 0jP: спуститесь вниз и вставьте шаблон в начало строки.
  5. 0<C-a>: перейти к первому столбцу и увеличить число на единицу.
  6. q: окончание записи макроса.

это дает:

1 aaa
2 bbb
ccc

теперь вы можете применять этот макрос, используя @q, сколько хотите. Если вам нужно увеличить значение на два, просто используйте CTRL-aCTRL-a вместо одного раза. Теперь вы можете применить этот макрос к последовательным строкам, например:

:.,$norm @q

добавит начальные номера строк для остальной части вашего файла.

person hochl    schedule 28.03.2012
comment
Если я правильно понимаю, вы копируете предыдущее число и увеличиваете его. Работает ли это, если число имеет больше цифр? Есть ли причина пробела между f и 0? - person Tamás Szelei; 28.03.2012
comment
Да, вы правильно это понимаете. Пробел важен, так как вы копируете все, включая пробел с f, поэтому вы копируете больше цифр. Так что да, это работает для чисел с более чем одной цифрой, только что попробовал до строки 1449 в файле :) Конечно, вы можете использовать любой другой символ разделения, tab приходит на ум. - person hochl; 28.03.2012
comment
О да. По какой-то причине я предположил, что 0 означает число, поэтому f переместилось бы на первое число. Я думаю, что это лучшее решение здесь. - person Tamás Szelei; 28.03.2012
comment
О, хорошо, однострочники тоже хороши, но обычно придумывать их более утомительно, чем просто записывать макрос. Мне нравятся макросы за их простоту использования и гибкость. - person hochl; 28.03.2012
comment
@hochl: думать о командах Ex не более утомительно, чем о командах нормального режима. Если вам утомительно использовать одну из этих команд, это означает, что ваш опыт работы с Vim не сбалансирован между ними. - person ib.; 28.03.2012
comment
Я часто добавляю zz в свой макрос, чтобы увидеть, что будет дальше. Тяжело, когда курсор внизу экрана. - person Luc M; 30.07.2015

:4,8s/^/\=line(".")-3." "    

будет делать то, что ты хочешь

если вам нужно количество = 2:

:4,8s/^/\=2*(line(".")-3)." " 

это даст вам 2,4,6,8,10

номера строк жестко закодированы в моем примере, вы можете использовать V, чтобы выбрать те строки, которые вы хотите изменить.

person Kent    schedule 28.03.2012
comment
Этот подход прост, универсален и не требует пояснений. - person Gagan; 04.01.2021

Вот такая пакость, но ведь жизнь складывается из этих. :)

ESC :r! for i in $(seq 1 10); do echo "This is line \#${i}"; done

Не кроссплатформенный.

person Noufal Ibrahim    schedule 28.03.2012

Выберите целевые строки в визуальном режиме, затем запустите команду Ex

:'<,'>s/^/\=(line('.')-line("'<")+1).' '
person ib.    schedule 28.03.2012

Я думаю, что все предложенные решения слишком сложны для запоминания, вы можете использовать его один раз, но тогда вам нужно вдаваться во все детали каждый раз, когда вы его используете (если вы используете его реже, чем раз в день или около того).

Я обнаружил, что сценарий визуального увеличения очень прост в установке и использовании. Как только он будет установлен в vim, вам просто нужно создать столбец из 0, выбрать его с помощью Ctrl-V и написать команду: I. Затем он будет автоматически генерировать увеличивающиеся числа в каждой строке. Есть и другие особенности:

  • начать с числа, отличного от 0
  • левые или правые номера пэдов с нулями (например, 001, ..., 015)
  • уменьшение или увеличение числа
  • увеличить более чем на 1
  • даты (но нужен дополнительный плагин), буквы алфавита, названия дней

Это решает более общую проблему, поскольку работает также в позиции, отличной от столбца 0, столбец должен быть просто выбран с помощью Ctrl-V.

Vimball плагина находится здесь или здесь.

person Gismo Ranas    schedule 15.01.2014

(если ваш vim поддерживает Perl — по умолчанию во многих дистрибутивах Linux): выберите строки в визуальном режиме (V) и выполните

:perldo s/^/++$z . " "/e

or

:4,8 perldo s/^/++$z . " "/e
person JJoao    schedule 23.01.2018

Плагин Nexus предоставляет тип Series и объект s1 этого типа, используемый следующим образом:

:4,8s/^/\=s1.next().' '/

Nexus также поставляется с объектом s0 Series, который дает 0 в качестве первого результата .next(). И s0, и s1 используют приращение в 1 шаг. Все объекты Series имеют метод .reset(), который возвращает им исходное значение. Объекты New Series могут быть созданы следующим образом:

let s2 = Series(0, 2)

который создает двухэтапный объект, отвечающий вашему второму запросу (выдает: 2, 4, 6, 8 и т. д.).

person dahu    schedule 28.03.2012

Менее гибкий, но легко запоминающийся метод — использовать плагин перенумерации, такой как Renumber.vim http://www.vim.org/scripts/script.php?script_id=189

Если номеров еще нет, как в ОП, на их место нужно вставить какое-то число. Renumber может обрабатывать фактический порядок, и он делает это на основе только первого числа.

В этом примере я использую <C-v>, чтобы вставить начальный номер во все строки, которые вы хотите пронумеровать.

4G<C-v>4jGI1 <Esc>gv:Renumber

Чтобы использовать шаги из двух

:Renumber s2

person Heikki Naski    schedule 28.03.2012