使用vi或vim注释掉由行号指定的多行代码


20

我从这个堆栈溢出问题中学到,可以使用vi/ vim注释掉指定范围的行号。例如,假设我有以下bash脚本:

#!/bin/bash

This
is
my
very
very
great
script

现在假设我想通过8注释掉行号6(包含单词veryverygreat)使用#注释字符。在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。我正在从PC使用SSH访问远程Ubuntu Linux群集。我没有使用Ubuntu Linux GUI。

Answers:


22

您可以使用:

:6,8s/^#//

但是使用“块可视化”选择模式要容易得多:转到第6行的开始,按Ctrl-v,向下到第8行,然后按x

还有“ NERD Commenter”插件。


2
NERD Commenter我认为这是去这里的方法!为此+1
user1146332 2013年

7

我知道您的问题指定使用vi或,vim但是这里有一些其他选项可以执行此操作而不必手动打开文件:

  • 佩尔

    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
这不是“必须手动打开文件”的问题,因为通常在编辑时,您可以决定在视觉检查时注释哪些行:)但是,可以肯定,这是完整性的一个很好的答案。
Paulo Almeida

2
@PauloAlmeida当然是正确的。我只是认为这会很有用,因为OP已经知道行号(因为第一个用于注释行的命令),并且无论如何,我展示的工具都可以应用于各种问题。
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选择行,然后按xdel

要他们回来吗?

ctrl+ v进行选择,然后I(大写i)#Esc


3

AFAIK,vi如今通常是vim的符号链接(尝试which vitype 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>

这样,您只需要在可视模式下选择行范围,然后按F7F8即可分别放置和删除注释。


1

有一个改变生活的插件,tpope称为vim-commentary

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

该插件提供

  • 理智
  • 适当缩进的注释
  • 不注释掉空/不必要的行

用法

  • 通过Vundle安装(或者我猜是Pathogen)。
  • 突出显示您的文字,然后按:,将显示为:<,'>
  • 在此处:<,'>Commentary输入评论,然后按Enter。
  • 宝 你完成了芽。

1

这个答案在这里是:1)显示正确的代码以粘贴到.vimrcvim 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则返回true的索引。由于if评估所有非零数字为真,因此我们必须比较输出以查看其是否大于-1。vim如果为false,则in的比较返回0,如果为true,则返回1,这是if希望正确评估的结果。

  • vnoremap <silent> <C-r> :<C-u>call Comment()<cr><cr>vnoremap表示在可视模式下映射以下命令,但不要递归映射(表示不要更改可能以其他方式使用的任何其他命令)。基本上,如果您是vim新手,请务必使用noremap以确保您不会破坏事物。<silent>意思是“我不想你的话,只是你的行动”,并告诉它不要在命令行上打印任何内容。<C-r>是我们要映射的东西,在这种情况下为ctrl + r(请注意,通过此映射,您仍可以在正常模式下将Cr正常用于“重做”)。C-u有点令人困惑,但是基本上可以确保您不会忘记视觉突出显示(根据此答案,它使您的命令从此处开始,只是告诉vim执行我们命名的函数,并且'<,'>我们想要的开始)。call<cr>指点击enter按钮。我们必须打一下它才能实际调用该函数(否则,我们只需call function()在命令行上键入,然后我们必须再次打它才能使我们的替代项一直执行(不确定原因,但无论如何)。

无论如何,希望这会有所帮助。这将使用vV或突出显示的内容C-v,检查第一行是否已注释,如果是,请尝试取消注释所有突出显示的行,如果没有注释,请在每行中添加额外一层注释字符。这是我想要的行为;我不仅希望它切换是否注释了每一行,因此在对这个问题提出了 多个问题之后,它对我来说非常有效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.