Как запустить: заменить только часть строки, а не всю?

15

У меня есть такая строка:

function my_function(argument, another argument, but there are spaces)

Я хочу заменить символы пробела (внутри имен аргумента) подчеркиванием. Таким образом, я хотел бы использовать:

:s/\ /_/g

но как я могу выбрать не применять его ко всей строке, а начинать, скажем, с позиции курсора? (Или третье слово)?

Feffe
источник
4
В регулярном выражении для описания текущей позиции курсора вы можете использовать атом \%#. Таким образом, вы можете использовать: :s/\v(%#.*)@<= /_/g. Который можно описать как пробел, которому предшествуют @<=символы ( ) после позиции курсора.
user9433424
1
Вы и Statox оба предложили \%#трюк, я приму его ответ, если вы не напишите один ... Но кто-нибудь из вас мог бы объяснить регулярное выражение немного более явно?
Феффе

Ответы:

15

Вы можете использовать следующее решение:

Сначала используйте v$для выделения текста от курсора до конца строки. Затем используйте следующую команду:

:s/\%V\ /_/g

\%VУказывают на изменение текста в ранее визуально выбранной области, см :h /\%V.

Если я возьму ваш пример:

function my_function(argument, another argument, but there are spaces)

Если мой курсор находится в 40-м столбце, и я использую команду, которую я только что написал, я получаю:

function my_function(argument, another argument,_but_there_are_spaces)

В ответ на ваш комментарий вы также можете использовать

  • \%# который соответствует от позиции курсора
  • \%>23c который соответствует после 23-го столбца.
  • \%>'m который совпадает после позиции знака

Видите :h /\%#, :h /\%>cи :h /\%>'m.

@ User9433424 дал способ использовать \%#в своем комментарии. Для шаблона с отметкой вы можете установить его с maпомощью:

:s/\%>'a /_/g

Ниже приведено объяснение шаблона, заданного @ User9433424:

:s/\v(%#.*)@<= /_/
:s/                    substitution command
   \v                  Enable the very magic mode
      %#.*             Any characters from the cursor position
           @<=         Check for matches just before what follows
              space    Followed by a space
               /_/     Substitute the matches by underscores

Вы захотите увидеть :h \vи:h /\@<=

statox
источник
Работает отлично! Но я не очень привык к визуальному выбору, и весь процесс кажется немного "тяжелым" ... Как вы думаете, могло бы быть что-то быстрее?
Феффе
Да, позвольте мне обновить мой ответ :)
statox
Пользователь 9433424 дал эту подсказку прямо перед вами, но вы ответили, так что я приму ваш ответ, если все в порядке - не могли бы вы объяснить шаблон регулярного выражения, который он использует немного больше? Я все еще
борюсь
Я пытался сделать ответ как можно более ясным, но если @ User9433424 пишет свой собственный ответ, не стесняйтесь принять его.
statox
1
Очень хорошее объяснение регулярного выражения, спасибо! И спасибо за ваш комментарий, чей ответ принять :)
Feffe
5

Вы можете использовать look behind ( :h \@<=), чтобы убедиться, что есть предшествующий символ '(') и граница конца слова ( :h \>), чтобы убедиться, что подстановка происходит там, где вы хотите.

Итак, с текстом:

function my_function(argument, another argument, but there are spaces)

запустив команду:

:s/\((.*\)\@<=\> /_/g

будет производить:

function my_function(argument, another_argument, but_there_are_spaces)

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

Antony
источник
2
Замена не всегда имеет известную отправную точку: это было только ... чтобы исправить странную серию опечаток, которые я сделал. Но ваш ответ, тем не менее, интересен, спасибо!
Feffe