viまたはvimを使用して、行番号で指定された複数行のコードをコメント化する


20

このStack Overflowの質問から、指定した範囲の行番号をコメントアウトするためにvi/ vimを使用することが可能であることを学びました。たとえば、次のbashスクリプトがあるとします。

#!/bin/bash

This
is
my
very
very
great
script

今、私は(言葉が含まれている8を通じて行番号6をコメントアウトしたいとしveryvery、および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。PCからSSHを使用して、リモートのUbuntu Linuxクラスターにアクセスしています。Ubuntu Linux GUIを使用していません。

回答:


22

次を使用できます。

:6,8s/^#//

しかし、はるかに簡単なのは、視覚ブロック選択モードを使用することです。6行目の先頭に移動し、を押してCtrl-v、8行目に移動し、を押しxます。

「NERD Commenter」プラグインもあります。


2
NERD Commenter私の意見ではここに行く方法です!+1
user1146332

7

私はあなたの質問の指定を使用して知っているvivimが、ここでこれを行うためのいくつかの他のオプションは、手動でファイルを開くことなく、次のとおりです。

  • 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当然です。OPは行番号を既に知っているため(コメントに使用される最初のコマンドが原因)、いずれにせよ、私が示すツールはさまざまな問題に適用できるため、これが役立つと思いました。
テルドン

4

vivimほとんどの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

知る限りでは、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>

ビジュアルモードで行範囲を選択し、およびを押すだけF7F8コメントを追加および削除することができます。


1

tpopeと呼ばれるこの人生を変えるプラグインがありますvim-commentary

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

このプラグインは以下を提供します

  • 正気
  • 適切にインデントされたコメント
  • 空の/不要な行をコメントアウトしません

使用法

  • Vundle(または私が推測する病原体)経由でインストールします。
  • テキストをハイライトし、押す:と次のように表示されます:<,'>
  • ここに「解説」:<,'>Commentaryと入力し、Enter キーを押します。
  • ボン あなたのできた芽。

1

この答えは、に貼り付けるために、正しいコードを表示する)1に、ここで.vimrc取得するためにvim 7.4+それを説明するために)ビジュアルモードと2で1つのショートカットでインデントレベルを維持しながらアンコメント/コメントブロックを行うこと。

コードは次のとおりです。

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':Executeはコマンドを呼び出します。この場合、を実行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()最初のものに2番目のものが含まれているかどうかを確認します。したがって、強調表示を開始した行を取得し、コメント文字が続く空白で始まるかどうかを確認します。match()これが当てはまるインデックスを返します-1。一致するものが見つからなかった場合。以来if評価するすべての非ゼロの数字が真であることが、我々はそれの-1より大きいかどうかを確認するために私たちの出力を比較する必要があります。比較in vimは、falseの場合は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ちょっと紛らわしいですが、基本的には、視覚的な強調表示を忘れないようにします(この答えによれば、コマンドを開始するの'<,'>は私たちが望むものです)。callここでは、指定した関数を実行するようにvimに指示し<cr>enterボタンを押すことを示しています。実際に関数を呼び出すには、1回押す必要があります(そうでない場合はcall function()、コマンドラインに入力したばかりで、代わりのものをすべて取得するためにもう一度押す必要があります(理由はわかりませんが、何でも)。

とにかく、うまくいけばこれが役立つ。これは、と強調し何もかかりますvVまたはC-v、最初の行をコメント化されているかどうかをチェックし、そうならば、すべての強調表示された行のコメントを解除しようとすると、そうでない場合、各行にコメント文字の追加の層を追加します。これは私の希望する動作です。それは後に私のために完璧に動作だから、僕は、それがブロックの各行がコメントされたかどうかを切り替えるにはしたくなかった尋ねる 複数の主題に関する質問を。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.