Vim: s замінити перші N <g події в рядку


13

У vim, інколи в мене є привід замінити перші кілька випадків матчу на лінії, але не кожен, хто хотів gби. наприклад:

a a a a a

до

b b b a a

Я знаю, що міг би скористатися :s/a/b/[enter]:[up][enter]:[up][enter], але це досить нудно при трьох повторах, у мене є рядки з потенційно 10+ замінами.
Я спробував:

  • :s/a/b/3g: vim поскаржився на слідів символів.
  • :s/a/b/3: змінює перше виникнення у цьому та наступних двох рядках.
  • 3:s/a/b: те саме, що і попереднє.
  • :s/a/b/g3: змінює всі події в цьому та наступних двох рядках.
  • :3s/a/b: змінює перше виникнення у рядку 3.
  • :/a/,3/a/s/a/b: змінює перше виникнення у кожному рядку між наступним aта третім рядком, що міститься aу файлі (із закликом скасувати, якщо потрібно).
  • :/a/,/\([^a]*a\)\{3\}/s/a/b/: змінює перше виникнення у кожному рядку між цим та наступним із 3 aс на ньому (і це не було б легко розширити для пошуку багато символів).

І різні інші схеми адресації, жодна з яких не працювала. Треба сказати, я дізнався неабияку інформацію про :sкоманду, яка намагалася знайти відповідь на цю проблему, але я все ще не вирішила її.

Хтось знає, як це зробити?

(бонусні бали за певний діапазон, наприклад, другий по четвертий події)


2
Я впевнений, що ви не можете цього зробити in vim, але щоб зробити це менш стомлюючим, чи знаєте ви про "n" та "." у візуальному режимі? Тобто ви використовуєте / pattern /, щоб знайти річ, яку потрібно змінити, змінити її за допомогою "cw" або будь-чого іншого, thn використовуйте "n" (просто n, без лапок), щоб знайти наступний шаблон і натисніть ". (просто період, без лапок), щоб виконати останню зміну.
Брюс Едігер

@BruceEdiger я знав про це, nі .хоч і не думав їх тут використовувати. Безумовно, покращення, дякую.
Кевін

s/a/=something/повинен зробити трюк ( :help sub-replace-=). Я не вільно володію Вімом, щоб somethingсписати биту.
Жиль "ТАК - перестань бути злим"

Примітка: :[up][enter]можна замінити &, що все ще не ідеально, але принаймні менш болісно.
Ков

Відповіді:


10

Спираючись на :s/pattern/replacement/gc ідею від Samus_ (яка, здається, є найпростішим способом забезпечення правильної роботи, коли шаблон міститься в рядку заміни), замінити 2-й по 4-й випадки в одному рядку:

:call feedkeys("nyyyq") | s/pat/string/gc

feedkeys()це функція, яка вводить рядок введення у чергу введення клавіатури. Сенс полягає в тому, щоб зробити підрахунок вперед, так що вам не доведеться турбуватися про втрату рахунку або переривання.

Для більш загального випадку, щоб замінити Mth на Nth входження в одному рядку на N, що перевищує або дорівнює дуже великому M :

:call feedkeys(repeat("n", M-1) . repeat("y", N-M+1) . "q") | s/pat/string/gc

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


Хм. Мені це подобається. Я також мав би змогу написати функцію для нього.
Кевін

8

Перше питання я би зробив:

:s/a/b
&&

Другий складніший, я не знаю способу зробити це автоматично, але ви можете запросити vim на кожен матч, як це:

:s/a/b/gc

Потім ви відповідаєте "ні" на перші n матчів, а "так" на інші.


Гм, я забув про це c, що, можливо, найкраще запропоноване рішення поки що. Я все одно повинен би порахувати, але я думаю, що це перший варіант, який би працював із замінами, які містять рядок пошуку.
Кевін

6
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a
a a a a a

:3,6g/^/let i=0 | while i<3 | s/a/b/ | let i+=1 | endwhile

a a a a a
a a a a a
b b b a a
b b b a a
b b b a a
b b b a a
a a a a a

1
Це добре, але він все ще страждає від проблеми, яку зазначив Гілл (на іншій посаді, яка, здається, була видалена), що працює лише тоді, коли заміна не містить шаблон. Хоча мені дуже подобається сценарна ідея.
Кевін

Справа краси!
єпископ

1

Я думаю, що це може спрацювати, спочатку замініть, а потім повторіть 2 рази:

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