Vim: вставлять одни и те же символы в несколько строк


306

Иногда я хочу отредактировать определенный визуальный блок текста в несколько строк.

Например, я бы взял текст, который выглядит так:

name
comment
phone
email

И чтобы это выглядело так

vendor_name
vendor_comment
vendor_phone
vendor_email

В настоящее время, как я бы сделал это сейчас ...

  1. Выберите все 4 строки строки блока, нажав, Vа затем jчетыре раза.
  2. Отступ с >.
  3. Вернитесь на одно письмо с h.
  4. Перейти в блок визуального режима с помощью Ctrlv.
  5. Выберите четыре строки вниз, нажав jчетыре раза. На этом этапе вы выбрали визуальные блоки 4x1 (четыре строки и один столбец).
  6. Нажмите C. Обратите внимание, что это в значительной степени отступ слева от одного столбца.
  7. Введите " vendor_"без цитаты. Обратите внимание на дополнительное пространство, которое мы должны были вернуть.
  8. Нажмите Esc. Это один из немногих случаев, когда я Escвыхожу из режима вставки. Ctrlcбудет редактировать только первую строку.
  9. Повторите шаг 1.
  10. Сделайте отступ в другом направлении <.

Мне не нужно делать отступ, если перед словами есть хотя бы один столбец пробела. Мне бы не понадобились пробелы, если бы мне не пришлось очищать визуальный блок c.

Но если мне нужно очистить, то есть ли способ сделать то, что я выполнил выше, без создания необходимого пробела с отступом?

Кроме того, почему редактирование нескольких строк одновременно работает только при выходе из режима вставки с Escболее чем Ctrlc?


Вот более сложный пример:

name    = models.CharField( max_length = 135 )
comment = models.TextField( blank = True )
phone   = models.CharField( max_length = 135, blank = True )
email   = models.EmailField( blank = True )

в

name    = models.whatever.CharField( max_length = 135 )
comment = models.whatever.TextField( blank = True )
phone   = models.whatever.CharField( max_length = 135, blank = True )
email   = models.whatever.EmailField( blank = True )

В этом примере я выполняю вертикальный визуальный блок над ., а затем снова вставляю его обратно в режиме вставки, то есть типа .whatever.. Надеюсь, теперь вы можете увидеть недостаток этого метода. Я ограничен только выбором столбца текста , которые все одинаковы в вертикальном положении .


9
Лучший способ: ":% s / ^ / vendor_ /"
Пол Томблин

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

3
Затем выделите строки, которые вы хотите изменить с помощью shift-V, и введите соответствующую команду поиска и замены - во втором примере:s/models\./\0whatever./
Пол Томблин

Множество способов достижения вышеуказанного. Чтобы полностью ответить на все части вопроса, затем часть 1), либо регулярное выражение, либо визуальный режим, который я редактирую, работает хорошо, как предлагается в ответах (я предпочитаю визуальный отбор в GVIM). Для части 2) макрос, пожалуй, самый простой, предложенный Брайаном Нилом. Лучший ресурс, о котором я знаю для всех этих видов "как", - "Practical Vim" от Drew Neil. Отличное быстрое чтение и легкий вес ссылки, когда вы забыли формулу. Надеюсь, что эта рекомендация кому-то поможет, она будет стоить усилий для многих пользователей VIM.
arcseldon

@ Пол: И если вы рассчитываете нажатия клавиш , вы можете заменить \0на &.
icktoofay

Ответы:


912
  1. Переместите курсор nв name.
  2. Войдите в режим визуального блока ( Ctrlv).
  3. Нажмите jтри раза (или 3j).
  4. Нажмите I(заглавная я).
  5. Введите vendor_. Примечание. Он будет обновлять экран только в первой строке - пока не Escбудет нажата кнопка (6.), после чего все строки будут обновлены.
  6. Нажмите Esc.

мини-скринкаст, демонстрирующий метод

В верхнем регистре Iдолжен использоваться, а не в нижнем регистре i, потому что нижний регистр iинтерпретируется как начало текстового объекта , который довольно полезен сам по себе, например, для выбора внутри тега block ( it):

мини-скринкаст, показывающий полезность текстового объекта 'it'


12
Я не мог заставить это работать в Windows (так как CTRL + V отображается для вставки в буфер обмена). Но Vim также сопоставил это с Ctrl + Q для версии Windows.
Арнестиг

2
@Ven: Vim на самом деле не занят в это время - он просто ждет, пока вы нажмете другую клавишу, и в итоге истечет время ожидания. Два эксперимента для вас: сначала попробуйте нажать escape, а затем сразу же нажать другую клавишу, например jили ^L. Вы должны видеть, что Вим не был занят в конце концов; это было просто ожидание. Во-вторых, попробуйте изменить значение 'timeout'на более низкое, например 80(вместо значения по умолчанию 1000), и заметьте, что оно истекает быстрее.
icktoofay

1
@icktoofay Похоже, переменная, которую вы хотите установить, timeoutlenне является timeout.
Jez

4
@ANjaNA: Если место, куда вы хотите вставить, находится в одном столбце (например, если числа имеют одинаковую длину), вы можете использовать ту же технику, кроме нажатия Aвместо I, который будет вставлен после выбранного блока, а не до. Если ваши строки имеют разную длину, это не сработает; Для этого мне нравится использовать подстановку, совпадающую с концом каждой строки, например, выбирая несколько строк и используя :s/$/inserted/.
icktoofay

3
Я должен был нажать стрелку вниз после нажатия esc, чтобы заставить это работать
GeoSword

69

Другой подход заключается в использовании команды .( dot) в сочетании с I.

  1. Переместите курсор туда, где вы хотите начать
  2. Нажмите I
  3. Введите префикс, который вы хотите (например vendor_)
  4. Нажмите esc.
  5. Нажмите, jчтобы пройти по линии
  6. Введите, .чтобы повторить последнее редактирование, автоматически вставляя префикс снова
  7. Быстро чередуйте между jи.

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

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


Приятно видеть другой подход.
Ибн Саид

Я предпочитаю это только на несколько строк. Гораздо проще выполнить ИМО.
Дэн Бешард

После того, как вы введете нужный префикс, вам не нужно нажимать клавишу выхода?
iamnotsam

41
  1. Выберите строки, которые вы хотите изменить, используя CtrlV.
  2. Нажмите:

    • I: Вставить до того, что выбрано.
    • A: Добавить после того, что выбрано.
    • c: Заменить то, что выбрано.
  3. Введите новый текст.

  4. Нажмите, Escчтобы применить изменения ко всем выбранным строкам.

4
Превосходно! Я бы просто выделил последний шаг Escдля новичков VIM, таких как я, - мне потребовалось некоторое время, чтобы понять, что изменения распространяются «позже»!
Bugs Bunny

1
Приятно, не знал про варианты "А" и "С" тоже.
hobbes3

Почему это не работает для v? Я могу сделать это с помощью Ctrl+V --> A, но vвыбор текста не работает - Aтолько добавляет к этой строке. Разве они не выбор? Кроме того, очень странно - Aдобавляется только в конец строки, если я расширяю визуальный блок до конца строки; в противном случае он добавляется везде, где заканчивается визуальный блок для каждой строки. Как будто он не распознает разницу между aи A.
Alex G

1
Мне нужно было использовать cвместо C, но он работал отлично. Спасибо
Тарол

29

Я использовал макрос для записи своих действий, а затем повторял бы его.

  1. Наведите курсор на первую букву имени .
  2. Нажмите, qqчтобы начать запись в буфер q.
  3. Нажмите, iчтобы перейти в режим вставки, введите vector_ , а затем нажмите, Escчтобы выйти из режима вставки.
  4. Теперь нажмите, 0чтобы вернуться к началу строки.
  5. Теперь нажмите, jчтобы пойти вниз.
  6. Теперь нажмите qснова, чтобы остановить запись.

Теперь у вас есть хороший макрос.

Напечатайте, 3@qчтобы выполнить ваш макрос три раза, чтобы выполнить остальные строки.


«Q» особенный (для «быстрого макроса»?)?
Питер Мортенсен

Как сделать макрос постоянным (работая в течение нескольких сеансов)?
Питер Мортенсен

@PeterMortensen Vim имеет функцию, называемую сессиями, в которой сохраняются буферы (и многие другие), на которые вы можете посмотреть.
Брайан Нил

27
:%s/^/vendor_/

или я что-то упустил?


Вам не хватает того факта, что это, скорее всего, подтекст в файле со многими другими строками, в которых vender_префикс нежелателен.
Дан Бешард

9
@dan Если нужен только подтекст, вы можете ограничить поиск набором номеров строк, например,1,4s/^/vendor_/
Брэд Кох

1
@BradKoch Интересно. Я не знал об ограничениях номера строки, спасибо за это.
Дэн Бешард

8
это интересно, но что более практично, это визуально заблокировать выбор с помощью Vи набрать текст :. Это будет префиксом выражения ed, с помощью :'<,'>которого ed будет применяться только к выделению с помощью:'<,'>s/^/vendor_/
Dolanor

12

Обновлено января 2016

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

  1. Переместите курсор nв name.
  2. Войдите в режим визуального блока ( ctrlv).
  3. Нажмите 3j
  4. Нажмите I.
  5. Введите vendor_.
  6. Нажмите esc.

визуальная иллюстрация

Обратите внимание, что это имеет меньше нажатий клавиш, чем принятый ответ (сравните Шаг 3). Мы просто посчитаем количество j действий для выполнения.

Если у вас включены номера строк (как показано выше) и вы знаете номер строки, на которую хотите перейти, то шаг 3 можно изменить на #, Gгде # - номер требуемой строки.

В нашем примере выше это было бы 4G. Однако при работе с несколькими номерами строк явный счет работает хорошо.


7

Я хотел закомментировать много строк в каком-либо файле конфигурации на сервере, на котором был только vi (без nano), поэтому визуальный метод также был громоздким. Вот как я это сделал.

  1. Открыть файл vi file
  2. Показать номера строк :set number!или:set number
  3. Затем используйте номера строк, чтобы заменить начало строки на «#», как?

:35,77s/^/#/

Примечание: цифры включительно, строки от 35 до 77, обе включены будут изменены.

Чтобы раскомментировать / отменить это, просто используйте :35,77s/^#//

Если вы хотите добавить текстовое слово в качестве комментария после каждой строки кода, вы также можете использовать:

:35,77s/$/#test/ (для таких языков, как Python)

:35,77s/;$/;\/\/test/ (для таких языков, как Java)

кредиты / ссылки:

  1. /unix/84929/uncommenting-multiple-lines-of-code-specified-by-line-numbers-using-vi-or-vim

  2. /unix/120615/how-to-comment-multiple-lines-at-once


Это было идеальное решение для меня, так как я часто использую только vim-tiny.
JSON C11

7

У вас также может быть случай использования, когда вы хотите удалить блок текста и заменить его.

Как это

Hello World

Hello World

к

Hello Cool

Hello Cool

Вы можете просто визуальным блоком выбрать «Мир» в обеих строках.

Введите cдля изменения - теперь вы будете в режиме вставки.

Вставьте материал, который вы хотите, и нажмите «Побег».

Оба отражаются вертикально. Он работает так же, как «I», за исключением того, что он заменяет блок новым текстом вместо его вставки.


6

Предположим, у вас есть этот файл:

something

name
comment
phone
email

something else
and more ...

Вы хотите добавить «vendor_» перед «name», «comment», «phone» и «email» независимо от того, где они появляются в файле .

:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc

cФлаг запросит подтверждение. Вы можете отказаться от этого, если вы не хотите, чтобы подсказка.


5

Альтернатива, которая может быть более гибкой:

Пример: для ввода текста XYZ в начале строки

:%norm IXYZ

Что тут происходит?

  • % == Выполнить в каждой строке
  • norm == Выполнить следующие ключи в обычном режиме
  • I == Вставить в начале строки
  • XYZ == Текст, который вы хотите ввести

Затем вы нажмете Enter, и это выполняется.

Специально для вашего запроса:

:%norm Ivendor_

Вы также можете выбрать определенный диапазон:

:2,4norm Ivendor_

Или выполнить в выбранном визуальном диапазоне:

:'<,'>norm Ivendor_

1
Можно ли отправлять последовательности клавиш типа <Esc> в режиме вставки (норма Iabc <ESC>), чтобы делать более интересные вещи?
батбрат

1
@batbrat Я только что понял это! Вы можете нажать ctrl-v ctrl-[«Esc», который возвращает вас в «обычный режим» для вашей обычной команды. Я просто проверил это с '<,'>norm Iaa^[ysiw", где ^[находится сбежавший Esc.
Обри Лавин

4
Use Ctrl+V to enter visual block mode
Move Up/Down to select the columns of text in the lines you want to comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line

этот метод работает для всех версий vim или требует каких-либо плагинов vim? причина, по которой я спрашиваю, это б / у, иногда она работает на некоторых машинах, но иногда нет. я не могу понять разницу. vim, который поставляется с git на windows - я не могу заставить его работать. на некоторых машинах Ubuntu и Centos Linux я не могу заставить его работать. У меня был успех в нескольких редких случаях, но я не мог воспроизвести успех. это тайна. кажется, ничего не происходит после того, как я нажму ESC.
davidj411

странно, это работает для меня сейчас. ничего не изменилось, кроме, может быть, звезд :), когда я искал решение моей проблемы, я нашел что-то на этой странице, хотя там упоминается что-то, что нужно искать в vim vim.wikia.com/wiki/Inserting_text_in_multiple_lines В Vim проверьте, что у вас есть функция блочных операторов (I, A и другие) вводится командой: version. Вывод должен включать + visualextra.
davidj411

Я хотел добавить комментарий вообще, а не к вашему ответу. Большинство из этих ответов говорят одно и то же, но используют разные слова. Мой мог предложить что-то другое и включил ссылку.
davidj411

2
  1. Ctrl + v для перехода в режим визуального блока
  2. Выберите линии, используя стрелки вверх и вниз
  3. Введите строчные буквы 3i(нажмите строчные буквы I три раза)
  4. I(нажмите заглавную I. Это переведет вас в режим вставки.)
  5. Напишите текст, который вы хотите добавить
  6. Esc
  7. Нажмите стрелку вниз
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.