Как скопировать каждую строку 11 раз, увеличивая последнюю «1» в каждой строке от 2 до 12

9

У меня есть несколько строк в файле, и я хотел бы скопировать каждую строку 11 раз (превратив каждую строку в 12 строк), и увеличить последнюю «1» в каждой строке, чтобы 12 строк имели «1» - «до» 12 ", где" 1 "изначально была. Могут быть и другие вхождения «1» в каждой строке, но «1», который я хочу увеличить, всегда будет последним вхождением в каждой строке. Другой способ взглянуть на это состоит в том, что последний «1» всегда следует после «/ nt /» - как в «/ nt / 1» (и это всегда будет единственное вхождение «/ nt / 1» в каждой строке) ,

Так, например, если у меня есть:

1stlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/1blah
3rdlineblahblahblah/nt/1blah

Я хочу превратить это в:

1stlineblahblahblah/nt/1blah
1stlineblahblahblah/nt/2blah
1stlineblahblahblah/nt/3blah
1stlineblahblahblah/nt/4blah
1stlineblahblahblah/nt/5blah
1stlineblahblahblah/nt/6blah
1stlineblahblahblah/nt/7blah
1stlineblahblahblah/nt/8blah
1stlineblahblahblah/nt/9blah
1stlineblahblahblah/nt/10blah
1stlineblahblahblah/nt/11blah
1stlineblahblahblah/nt/12blah
2ndlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/3blah
...

Я ранее нашел команду:

:for i in range(0,12) | put ='1stlineblahblahblah/nt/'.i.'blah' | endfor

работает для этой цели, но мне придется вручную запускать эту команду для каждой строки и вводить каждую строку (или копировать и вставлять ее) самостоятельно. Есть ли способ взять строки, которые уже есть в файле, и просто выполнить одну команду, которая превращает каждую строку в двенадцать, как я описал?

Заранее спасибо всем, кто может мне помочь с этим. Я также просто хотел отметить, что это мой второй вопрос, и я был рад получить несколько быстрых и эффективных решений моего первого вопроса, за что я был очень благодарен.

ablewasiereisawelba
источник

Ответы:

8

Вот замена, которая решает проблему:

:%s/\(.*\)1\(.*\)/\=join(map(range(1, 12), 'submatch(1) . v:val . submatch(2)'), "\n")

Подстановка соответствует каждой строке, которая содержит «1» и захватывает текст до {c1}и после {c2}последней «1». Для каждой согласованной линии, диапазон чисел от одного до двенадцати из {n}будут отображены создать двенадцать строк формы {c1}{n}{c2}. Каждая группа из двенадцати строк заменяет связанную с ней первоначально согласованную линию.

См :h sub-replace-expression.

djjcast
источник
2
Вау, отличная однострочная команда. Я помню, что вы также нашли элегантное однострочное решение для первого вопроса, который я задал несколько недель назад. Очень хорошая работа. Большое спасибо. Кроме того, я предполагаю, что есть способ поместить это в файл _vimrc, чтобы я мог выполнить простую для запоминания команду или функцию, не набирая всю строку выше (или не просматривая список предыдущих команд), но Я еще недостаточно знаком с синтаксисом _vimrc, чтобы знать, как это сделать.
ablewasiereisawelba
10

Вы можете сделать это путем

  1. запись макроса, затем
  2. используя команду globalex для выполнения макроса n раз для каждой строки в файле.

После записи макроса отмените изменения, сделанные во время записи, или будет n + 1 дополнительных строк для первой строки и n для последовательных строк.

Запишите макрос в aрегистр с помощью

qayyp$?\d<CR><C-A>q

Это записывает в register a( qa...q) следующую команду:

  • yyp: дублировать текущую строку
  • $: перейти к концу строки
  • ?\d<CR>: поиск в обратном направлении для одной цифры
  • <C-A>: увеличить цифру под курсором на единицу

Когда макрос записан, удалите изменения, сделанные во время записи, либо отменив ( uu) или удалив текущую строку ( dd). Затем повторите макрос 11(или любое количество раз) для каждой строки в файле с помощью глобальной команды:

:g//normal 11@a
jjaderberg
источник
2
Это сработало! Очень мило спасибо. Сначала у меня была проблема с выделением всего Ctrl-a вместо добавления, потому что я использую gVim в Windows ... но я сделал быстрый поиск и нашел этот поток - stackoverflow.com/questions/289681/… - где я использовал предложение поместить nnoremap <kPlus> <Ca> nnoremap <kMinus> <Cx> в _vimrc, чтобы я мог использовать клавиши «+» и «-» для сложения и вычитания. Кроме того, глобальной командой для меня должно было быть: g // normal 11 @ a, но это было легко понять. Спасибо!
ablewasiereisawelba
6

Два пути:

Используйте макрос!

Начиная с

1stlineblahblahblah/nt/1blah
2ndlineblahblahblah/nt/1blah
3rdlineblahblahblah/nt/1blah

С вашим курсором на первой строке

qqyyp$?\d<CR><Ctrl-a>q
10@q

Который делает:

qq Начать запись макроса в регистр q

yyp выдерните текущую строку и вставьте ее ниже

$?\d<CR> Идите до конца строки и найдите первую цифру, оглядываясь назад.

<Ctrl-a> Увеличение числа

q Прекратите запись макроса.

Это оставляет вас с:

1stlineblahblahblah/nt/1blah
1stlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/2blah
2ndlineblahblahblah/nt/3blah

С курсором на второй строке. Просто повторите этот макрос столько раз, сколько необходимо (например, повторите это десять раз с 10 @ q). Если вы хотите автоматизировать этот процесс для каждой строки, выполните его глобально для каждой строки:

:g//normal 11@q

В качестве альтернативы, с более новой версией vim: вставьте нужную строку сколько угодно раз, визуальный блок выберите цифру, которую вы хотите увеличить, и нажмите g <Ctrl-a>. Это должно увеличивать все числа в визуальном блоке по вашему желанию. Однако это более ручной процесс.

fruglemonkey
источник
1
Круто, я не знал о g <c-a>пути. Спасибо, что поделился.
KBA стоит с Моникой
1
@fruglemonkey Первая часть вашего ответа такая же, как и выше, но, тем не менее, спасибо. Вторая часть, я думаю, не работает для меня (если я не делаю что-то не так), поэтому я не должен использовать правильную версию.
ablewasiereisawelba
5

Я считаю, что проще всего использовать макросы для подобных задач. Просто начните запись макроса с q+ имя регистра и выполните задачу один раз. Я вижу здесь одно повторяемое задание:

  • Выберите строку
  • дергать
  • вставить (поставит вас в следующей строке)
  • идти до конца строки
  • вернуться на одно слово
  • увеличение на единицу

Теперь запишите необходимые нажатия клавиш для регистрации aв обычном режиме:

qayyp$b<c-a>.

Снова удалите строку, чтобы проверить, дает ли выполнение макроса 11 раз правильный результат для одной строки:

11@a

Оно делает! Итак, давайте снова отменим и автоматизируем весь процесс во втором макросе b:

qb11@aj

Теперь вы можете выполнить @bдо конца файла, и он должен произвести вывод, который вы хотите. Звучит сложно, но на самом деле вы не привыкли к типичным шаблонам редактирования.

кба стоит с моникой
источник
Я не уверен, что делаю что-то не так, но, похоже, это не работает. Я следовал тому, что вы написали, но, возможно, я что-то неправильно понял или что-то не выполнил должным образом. (Я получаю увеличенный первый номер строки, а не последний номер строки.) Спасибо за ответ.
ablewasiereisawelba
3
Я думаю, что первый макрос должен быть qaVyp$b<c-a>. Или лучше, просто qayyp$b<c-a>.
Карл Ингве Лервог
1
Спасибо, @ KarlYngveLervåg, ты прав, я исправил макрос.
КБА стоит с Моникой
2
Argh :( спасибо за тщательность @ablewasiereisawelba. Я думаю, что макрос qqyyp$?\d<CR><Ctrl-a>qот @fruglemonkey и @jjaderberg лучше, так как он ищет последний номер. Я изменю его на полноту.
kba стоит с Моникой
2
@kba Я просто подумал, что если кто-то потратит время и усилия, чтобы ответить на мой вопрос, я мог бы хотя бы попробовать его решение - даже если бы я уже нашел рабочее решение от кого-то другого. Я ценю твои усилия - и если тебе от этого станет легче, ты все еще впереди меня. :)
ablewasiereisawelba
2

Сохраните следующий макрос и используйте его для каждой строки:

qqyy11p/\/\zs1<CR><C-v>10jg<C-a>q

Основное отличие от других ответов заключается в том, что при этом используется g<C-a>выбор столбца, который увеличивает каждую строку на другое число. Проверьте :help v_g_CTRL-Aдля получения дополнительной информации. Я также использовал, \zsчтобы выбрать начальную позицию шаблона, так что курсор останавливается на числе после поиска.

Обратите внимание, что для этого вам нужна последняя версия Vim.

Витор
источник
1
@fruglemonkey также предложил это . Это классная функция, хотя и довольно свежая (по стандартам vim), начиная с 7.4.754, которая еще не поставлена ​​на все дистрибутивы.
КБА стоит с Моникой
Пропустил это извините
Vitor
1
@Vitor У меня просто есть gVim 7.4, поэтому я не думаю, что смогу сделать g<C-a>то же самое @fruglemonkey, на которое вы ссылались, но спасибо за ответ. Я должен отметить, что при попытке вашего макроса - непосредственно перед тем, как я доберусь до g<C-a>детали, это не последний символ «1», который я хочу увеличить, который подсвечивается блоком, но вместо этого это символ перед первым «1 msgstr "символ, выделенный блоком. (Кроме того, я думаю, что это было бы yy11pи 10jв макросе, так как я собираюсь добавить 11 строк - всего 12).
ablewasiereisawelba
1
Спасибо за ваш отзыв. Я обновил ответ соответственно. Решил использовать \zs, но я мог бы просто добавить lпосле <CR>.
Витор
1
Возможно, в вашем vimrc есть некоторые настройки, которые влияют на поиск по регулярному выражению. Попробуйте снова, начиная с Vim vim -u NONE. Я только что сделал это, и это работает отлично! На самом деле, поиск не будет соответствовать первому 1, потому что для этого требуется предшествующий слеш.
Витор