Коментуючи кілька рядків коду, визначених номерами рядків, використовуючи vi або vim


20

З цього питання про переповнення стека я дізнався, що можна використовувати vi/ vimкоментувати визначений діапазон номерів рядків. Наприклад, припустимо, у мене є такий скрипт bash:

#!/bin/bash

This
is
my
very
very
great
script

Тепер припустимо , що я хочу , щоб закомментировать номера рядків 6 по 8 (які містять слова very, veryі great) , використовуючи #символ коментаря. У vi/ vimя можу просто ввести, :6,8s/^/#щоб отримати наступне:

#!/bin/bash

This
is
my
#very
#very
#great
script

який коментує рядки 6 - 8.

Моє питання, чи можна ввести подібний один вкладиш , який буде видаляти на #символ коментаря з рядка 6 до 8 (але не будь - яких інших коментував рядків у файлі)?

Сказавши це, я розумію , що є деякі дебати про те чи я на самому справі з допомогою viабо vim. На практиці я відкриваю файл script.shіз командою vi script.sh. Крім того, коли я набираю команду which vi, я отримую /usr/bin/vi. Тим не менш, коли я просто набираю viі натискаю Enter, я отримую це:

~                              VIM - Vi IMproved
~
~                               version 7.2.330
~                           by Bram Moolenaar et al.
~                 Vim is open source and freely distributable
~
~                           Sponsor Vim development!
~                type  :help sponsor<Enter>    for information
~
~                type  :q<Enter>               to exit
~                type  :help<Enter>  or  <F1>  for on-line help
~                type  :help version7<Enter>   for version info

що, здається, підказує, що я насправді використовую vim. Я отримую доступ до віддаленого кластера Ubuntu Linux за допомогою SSH з мого ПК. Я не використовую графічний інтерфейс Ubuntu Linux.

Відповіді:


22

Ви можете використовувати:

:6,8s/^#//

Але набагато простіше використовувати режим блокування візуального вибору: Перейдіть до початку рядка 6, натисніть Ctrl-v, перейдіть до рядка 8 і натисніть x.

Також є плагін "NERD Commenter" .


2
NERD Commenterна мій погляд, це шлях піти сюди! +1 для цього
користувач1146332

7

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

  • Perl

    perl -ne 'if($. <=8 && $. >= 6){s/^\s*#//;}print' foo.sh 
    
  • Версія Perl> = 5.10

    perl -ne '$. ~~ [6..8] && s/^\s*#//;print' foo.sh 
    

    Це дозволить роздрукувати вміст файлу, його можна перенаправити на інший ( > new_file.sh) або використовувати iдля редагування файлу на місці:

    perl -i -ne '$. ~~ [6..8] && s/^\s*#//;print' foo.sh 
    
  • sed

    sed '6,8 s/^ *#//' foo.sh
    

    Знову ж таки, щоб змінити оригінальний файл на місці, використовуйте i:

    sed -i '6,8 s/^ *#//' foo.sh
    
  • awk/ gawkтощо:

    gawk '(NR<=8 && NR>= 6){sub("^ *#","")}{print}' foo.sh
    
  • Чисто bash:

    c=1; while read line; do 
      if [ $c -ge 6 ] && [ $c -le 8 ]; then 
         echo "${line/\#/}"
      else 
         echo $line 
      fi
      let c++; done < foo.sh
    

1
Справа не стільки в тому, що "потрібно вручну відкривати файл", адже зазвичай ви вирішуєте, які рядки коментувати при візуальному огляді, редагуючи :) Але, звичайно, це хороша відповідь на повноту.
Пауло Альмейда

2
@PauloAlmeida ти прав, звичайно. Я просто подумав, що це може бути корисним, оскільки ОП вже знає номери рядків (через першу команду, яка використовується для їх коментування), і, у будь-якому випадку, інструменти, які я показую, можуть бути застосовані до різноманітних проблем.
terdon

4

viє символічним посиланням на vimбільшість дистрибутивів GNU / Linux, тому ви справді використовуєтеvim під час введення vi.

Щоб видалити коментарі, ви можете ввести: :6,8s/^#//або :6,8s/^\s*#//відкинути деякий провідний пробіл перед # символом.


1
Дуже дякую. Здається, можуть бути помилки друку. Може бути , це повинно бути :6,8s/^#//і 6,8s/^\s*#//?
Андрій

3

Ви, ймовірно, використовуєте vim.tiny. У будь-якому випадку ви можете видалити початкові коментарі за допомогою:

:6,8s/^#//

Звичайно, якщо ви вставите їх іншим способом (наприклад, з додатковим місцем), можливо, вам доведеться видалити все, що там є. З повним vim, візуальний вибір стовпців та вставлення / видалення символів - простіший спосіб зробити те ж саме.


3

Особисто мій улюблений спосіб - це використання режиму візуального блоку

ctrl+ vдля входу в режим візуального блоку використовуйте клавіші зі стрілками або hjkl для вибору рядків і натисніть xабо del.

Хочете їх назад?

ctrl+ vзробіть вибір, тоді I(велика i)#Esc


3

AFAIK, vi, як правило, є символьним посиланням vim в даний час (спробуйте which viабо type viпотім слідуйте за посиланнями). Можливо, навіть /usr/bin/vi-> /etc/alternatives/vi->/usr/bin/vim.basic .

Особисто для видалення декількох рядків коментарів я вважаю за краще вибирати вертикальний блок через CtrlVта видаляти його. Якщо вам потрібно додати символ коментаря до кількох рядків, ви можете CtrlV, тоді ShiftIвведіть #і Esc, і коментар буде доданий до кількох рядків.


2

Наведені вище відповіді, використовуючи

:6,8s/^#//

є ідеальним рішенням, але трохи громіздким. Це можна спростити, визначивши нові команди в ~/.vimrc.

command -range=% C :<line1>,<line2>s/^/#/
command -range=% D :<line1>,<line2>s/^#//

І ви можете просто набрати

:6,8C
:6,8D

розмістити / видалити команду.

Якщо вам подобається візуальний режим, ви можете визначити карти

map <F7> :s/^/#/<CR>
map <F8> :s/^#//<CR>

Такий, що вам потрібно лише вибрати діапазон рядків у візуальному режимі, натиснути F7і F8відповідно поставити та видалити коментарі.


1

Існує цей життєвий плагін, який tpopeназивається callvim-commentary

https://github.com/tpope/vim-commentary

Цей плагін забезпечує :

  • Розсудливість
  • Правильно відступні коментарі
  • Не коментує порожні / непотрібні рядки

Використання :

  • Встановити через Vundle (або Патоген, я думаю).
  • Виділіть текст і натисніть, :що відображатиметься як:<,'>
  • Введіть тут коментар :<,'>Commentaryі натисніть клавішу Enter.
  • Бом. Ваш готовий бутон.

1

Ця відповідь тут: 1) покажіть правильний код, який потрібно вставити в a, .vimrcщоб отриматиvim 7.4+ зробити блок коментування / розкоментувати, зберігаючи при цьому рівня відступу з 1 ярликом в візуальному режимі і 2) , щоб пояснити це.

Ось код:

let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.[ch]    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.cpp    let b:commentChar='//'
autocmd BufNewFile,BufReadPost *.py    let b:commentChar='#'
autocmd BufNewFile,BufReadPost *.*sh    let b:commentChar='#'
function! Docomment ()
  "make comments on all the lines we've grabbed
  execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e'
endfunction
function! Uncomment ()
  "uncomment on all our lines
  execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e'
endfunction
function! Comment ()
  "does the first line begin with a comment?
  let l:line=getpos("'<")[1]
  "if there's a match
  if match(getline(l:line), '^\s*'.b:commentChar)>-1
    call Uncomment()
  else
    call Docomment()
  endif
endfunction
vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>

Як це працює:

  • let b:commentChar='//': Це створює змінну в vim. bтут відноситься до області, яка в даному випадку міститься в буфер, тобто відкритий в даний момент файл. Персонажі ваших коментарів - це рядки, і їх потрібно загорнути в лапки, лапки не є частиною того, що буде замінено при зміні коментарів.

  • autocmd BufNewFile,BufReadPost *...: Автокоманди спрацьовують у різних речах, у цьому випадку вони спрацьовують, коли новий файл чи прочитаний файл закінчується певним розширенням. Після запуску виконайте таку команду, яка дозволяє нам змінитиcommentChar залежно від типу файлу. Є й інші способи зробити це, але вони більш заплутані для новачків (як я).

  • function! Docomment(): Функції оголошуються починаючи з functionі закінчуючи endfunction. Функції повинні починатися з великої літери. що !гарантує , що ця функція переопределяет всі попередні функції , визначені як Docomment()з цією версією Docomment(). Без того! мене виникли помилки, але це могло бути тому, що я визначав нові функції через командний рядок vim.

  • execute '''<,''>s/^\s*/&'.escape(b:commentChar, '\/').' /e': Виконання викликів команди. У цьому випадку ми виконуємо substitute, який може приймати діапазон (за замовчуванням це поточний рядок), наприклад, %для всього буфера або '<,'>для виділеного розділу. ^\s*це регулярне вираження, щоб відповідати початку рядка з подальшим розміром пробілу, до якого потім додається (у зв'язку з &). .Тут використовується для конкатенації, так як escape()не може бути загорнуті в лапки. escape()дозволяє уникнути символу, commentCharякий відповідає аргументам (у цьому випадку \та /), попередньо додавши їх до а \. Після цього ми знову об'єднуємося з кінцем нашогоsubstitute рядка, яка маєeпрапор. Цей прапор дозволяє нам мовчки провалюватися, це означає, що якщо ми не знайдемо відповідність на заданій лінії, ми не будемо на це кричати. В цілому цей рядок дозволяє нам поставити символ коментаря, а потім пробіл перед першим текстом, тобто ми збережемо рівень відступу.

  • execute '''<,''>s/\v(^\s*)'.escape(b:commentChar, '\/').'\v\s*/\1/e': Це схоже на нашу останню величезну довгу команду. Унікальний для нас цей \v, що гарантує, що нам не доведеться уникати наших (), і 1що стосується групи, яку ми створили з нашою (). В основному ми співставляємо рядок, який починається з будь-якої кількості пробілів, а потім наш символ коментаря, а потім будь-яка кількість пробілів, і ми зберігаємо лише перший набір пробілів. Знову ж таки, eдозвольте ми мовчки провалюватися, якщо у нас немає символу коментарів у цьому рядку.

  • let l:line=getpos("'<")[1]: це задає змінну так, як ми це робили з нашим характером коментарів, але lстосується локальної області (локальної для цієї функції). getpos()отримує позицію, в цьому випадку, початку нашого висвітлення, і[1] засоби, які ми дбаємо лише про номер рядка, а не про інші речі, наприклад номер стовпця.

  • if match(getline(l:line), '^\s*'.b:commentChar)>-1: ти знаєш, як ifпрацює. match()перевіряє, чи містить перша річ друга, тому ми захоплюємо рядок, з якого ми розпочали виділення, і перевіряємо, чи не починається пробіл з подальшим позначенням коментаря. match()повертає індекс там, де це правда, і -1якщо не знайдено збігів. Оскільки ifоцінює всі ненульові числа справжніми, ми маємо порівняти результат, щоб побачити, чи більший він від -1. Порівняння vimповернень 0, якщо неправдиво, і 1, якщо справжнє, що ifхоче бачити, щоб правильно оцінити.

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>: vnoremapозначає відобразити наступну команду у візуальному режимі, але не відображати її рекурсивно (тобто не змінюйте жодних інших команд, які можуть використовуватися іншими способами). В основному, якщо ви новачок у вим, завжди використовуйте, noremapщоб переконатися, що ви не порушите справи. <silent>означає "Я не хочу твоїх слів, а лише твоїх дій", і вказує не друкувати нічого в командному рядку. <C-r>це те, що ми відображаємо, це ctrl + r в цьому випадку (зауважте, що ви все одно можете використовувати Cr для нормального режиму з цим відображенням у звичайному режимі). C-uце щось заплутано, але в основному це гарантує, що ви не втратите свого візуального підсвічування (відповідно до цієї відповіді, це змушує вашу команду розпочати, з '<,'>чого ми хочемо).call тут просто підказується vim виконувати функцію, яку ми назвали, і <cr>стосується натискання наenter кнопки. Нам потрібно один раз натиснути його, щоб насправді викликати функцію (інакше ми просто набрали call function()командний рядок, і нам доведеться натиснути її знову, щоб наші замінники пройшли весь шлях (не дуже впевнений, чому, але що б там не було).

У будь-якому випадку, сподіваємось, це допомагає. Це буде приймати що - або підсвічені v, Vабо C-v, перевірити , якщо перший рядок коментарів, якщо так, спробуйте розкоментувати всі виділені рядки, а якщо немає, додати додатковий шар символи коментаря до кожного рядка. Це моя бажана поведінка; Я не просто хотів, щоб він перемикав, коментували чи ні кожен рядок у блоці, тому він прекрасно працює для мене після того, як задав кілька запитань з цього приводу.

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