Як скопіювати кожен рядок 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

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

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

Відповіді:


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.


2
Нічого собі, чудова однолінійна команда. Я пам’ятаю, що ви також знайшли елегантне однолінійне рішення для першого питання, яке я задав кілька тижнів тому. Дуже приємна робота. Дуже дякую. Крім того, я здогадуюсь, що є спосіб помістити це у файл _vimrc, щоб я міг виконати просту запам'ятовувану команду чи функцію, не набираючи увесь рядок вище (або не потрібно прокручувати список попередніх команд), але Я ще недостатньо знайомий із синтаксисом _vimrc, щоб знати, як це зробити.
capawasiereisawelba

10

Ви могли це зробити за допомогою

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

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

Запишіть макрос до aреєстру за допомогою

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

Це записує в регістр a( qa...q) таку команду:

  • yyp: дублює поточний рядок
  • $: перехід до кінця рядка
  • ?\d<CR>: пошук назад для однієї цифри
  • <C-A>: цифра приросту під курсором на одиницю

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

:g//normal 11@a

2
Це спрацювало! Дуже приємно, дякую. Спочатку у мене була проблема з Ctrl-підсвічуванням всього, а не додаванням, тому що я використовую gVim у Windows ... але я швидко здійснив пошук і знайшов цю тему - stackoverflow.com/questions/289681/… - де я використав пропозицію покласти nnoremap <kPlus> <Ca> nnoremap <kMinus> <Cx> у _vimrc, щоб я міг використовувати клавіші "+" та "-" для додавання та віднімання. Також глобальною командою для мене було: g // normal 11 @ a, але це було легко зрозуміти. Дякую!
capawasiereisawelba

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>. Це повинно збільшувати всі числа у візуальному блоці за вашим бажанням. Це, однак, більш ручний процес.


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, ти маєш рацію, я виправив макрос.
kba виступає з Монікою

2
Арг: (дякую за ретельне @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, яка ще не поставлена ​​у всі дистрибутиви.
kba стоїть з Монікою

Пробачив
Витор,

1
@Vitor У мене просто gVim 7.4, тому я не думаю, що я можу зробити g<C-a>це @fruglemonkey, про який ви зверталися, але дякую за відгук. Слід зазначити, що при спробі макросу - якраз перед тим, як перейти до g<C-a>частини, я не останній символ "1", який я шукаю, щоб збільшити, виділяється блоком, а натомість це символ перед першим "1 "персонаж, який виділяється блоком. (Крім того, я думаю, це було б yy11pі 10jв макросі, оскільки я хочу додати 11 рядків - загалом 12.)
capawasiereisawelba

1
Дякуємо за ваш відгук. Відповідно я оновив відповідь. Вирішив використовувати \zs, але я міг так само просто додати lпісля <CR>.
Vitor

1
Можливо, у вашому vimrc є певні налаштування, які впливають на пошук регулярних виразів. Спробуйте ще раз, починаючи з Vim vim -u NONE. Я щойно це зробив, і це прекрасно працює! Насправді, немає способу пошуку відповідати першому 1, оскільки він вимагає попередньої косої риски.
Вітор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.