元の単語を入力せずにVimで検索および置換する方法


53

Vimの「検索と置換」ワークフローを最適化したいと思います。あなたのほとんどもそうだと思うので、それは私が頻繁に行うことです。通常の行に沿って何か- ブロックをコピーし、いくつかの場所で変数の名前を変更します。おそらく、「コードをコピーして貼り付ける理由」の反射を引き起こす可能性がありますが、その道をたどらないでください...多くの有効なユースケースがあります:)

私は、検索コマンドと置換コマンドをよく知っています::sまたは:%s、しかし、私はそれらが好きではありません。検索する完全な変数名と変更する名前の両方を入力する必要があります。たぶん、タイピングの量を修正するより良い方法があります:%sか?私はしばしば長い説明的な変数名を使用するので、それは本当に私にとって大きな問題です。また、変数名を最初から入力するのがタイプミスになりやすく、タイプミスを見つけるのに時間と頭脳を消費することも好きではありません。一度入力してから、可能な場合は完全に回避するために、コピーして貼り付けることをお勧めします。

現在のワークフローでは、movement / yank / select / search / putの組み合わせを使用してファイル内を移動し、1つずつ置き換えます。これは素晴らしいことではありませんが、完全な変数名を入力しなくて済むという利点があります。周囲の状況に応じて最初の数文字を入力する/か、別の移動コマンド(例:)を使用fxしてveから、単語全体を選択する必要があります。また、インスタンスごとに繰り返す必要があることも気にしません。各変更を確認せずに、完全な検索置換を実行することはありません。しかし、1回のキーストロークで置換アクションを繰り返すことができれば非常に望ましいでしょう(この方法ではできません)。各交換は、通常のようなものでn、その後ve、その後p(またはさらに悪いです"0p

もっと速い方法はありますか?


1
.最後の「コマンドブロック」を繰り返します(正確な用語は不明です。例:move + action + text。for exemple:( cwtoto<Esc>カーソルから単語の末尾に「toto」でc/foo<enter>bar<Esc>変更)、 (カーソルから「 foo」、「bar」に置き換えます。その後、移動できます(カーソル、hjkl、または数値+ hjkl(n回実行)、G(ファイルの最後に移動)、/ something(直前に移動)何か」)など)を押して.から、同じ「コマンドブロック」をやり直します
オリビエデュラック

私はこれをかなり使います!ただし、単語をヤンクしてから複数の場所で別の単語を置き換える場合は機能しません。それが私が問題を抱えている主なユースケースであり、のようなものになりn ve "0pます。残念ながらこれを複製することはできません.
ジョエル

5
n ce ctrl-r 0 <esc> n.n.n.n.n.n.
リッチな

@Joelでは、マクロを記録し(qa、次に必要なものすべて、q:マクロaを作成)、それから:aを使用して再生します(通常は134 @ aで134回実行します)。マクロは必要に応じて詳細に設定できます(例:何かを見つけ、適切な場所に移動し、次に単語をその場所に移動し、適切な場所に移動して、より良い位置で再び呼び出せるようにする)
オリビエデュラック

1
この質問から、サイト上の他の質問よりも便利なVIMトリックを学びました。ありがとうございました!
-dotancohen

回答:


81

私は実際にあなたとかなり似たワークフローを持っています(似ているブロックをコピーして貼り付け、:s変数名を変更するために使用しています)。特に、使用する変数を除いて似た行をたくさん書いているとき。しかし、私があなたが役に立つと思うかもしれないことをいくつかします。

一般的なvimのこと

  1. 最初に役立つのは、:s//foo/g最後に使用した検索用語をすべて入力し、それをfooに置き換えることです。それだけで多くの時間を節約できますが、アスタリスクコマンド(現在のカーソルの下の単語を検索)と組み合わせると、時間を大幅に節約できます。たとえば、すべてを変更fooするのspamではなく、

    :%s/foo/spam/g
    

    fooとspam(長い変数である可能性があります)の両方を入力する必要があるため、fooに移動して次の操作を実行できます。

    *:%s//spam/g
    

    このようにして、変更する変数の名前を検索することですばやく取得できます。その後、入力する必要はありません。これは、現在使用してnいる多くのワークフローでもうまく機能します。hlsearch交換する変数がどこにあるかを視覚的に確認できるため、オンにすることも役立ちます。

    (サイドノート:アスタリスクコマンドはつまり、単語の境界を追加する\<と、\>カーソルの下の単語の周りにあなたはこの、使用したくない場合。g*代わりに。)

  2. 単一のキーストロークで置換アクションを繰り返すことができれば、はるかに望ましいでしょう

    を使用@:して、最後の代替コマンドをやり直すことができます。:sたくさんの行でコマンドを実行したい場合は便利ですが、すべての行が機能するわけで:%sはありません。別のオプションは、確認フラグ:%s///gcです。これにより、入力するyn、出現するたびに、置換するかどうかを決定できます。

    以下のようDestyが指摘し、あなたも行うことができます&し、最後の置換コマンドを再実行しますが、これはすることに注意してくださいではない、あなたの旗を保つ(などglobalconfirm)。それが良いか悪いかはあなたの個人的な意見に依存します。これを使用したいが、フラグも保持したい場合は、次のようにすることができます

    nnoremap & :&&<cr>
    
  3. ファイル内のすべての一致ではなく、ブロック内のすべての出現を変更する場合は、常にブロックの視覚的な選択を使用できます。

    :'<,'>
    

    代わりに、選択した行に制限します。アスタリスクのアプローチと組み合わせると、これは非常に便利です。さらに、同じ行ブロックで複数の代替コマンドを作成している場合gv、同じ行を再選択して別のコマンドを実行できます。(それ:substituteが通常のコマンドであるかどうか)

    別の代替コマンドを実行する場合、同じ行で 動作するため、同じ行を再選択する必要ありません:'<,'>。ただし、入力する方が便利です

    gv:s
    

    のではなく

    :'<,'>s
    

好きなプラグイン/マッピング

  1. 私はアスタリスクアプローチ.vimrcを拡張する次のマッピングを持っているので、新しい目的の名前を入力するだけです:

    "(R)eplace all
    nnoremap <leader>r yiw:%s/\<<C-r>"\>//g<left><left>
    

    これを使用するには、変更したい単語にカーソルを置き、入力するだけで<leader>rNewVarName<cr>完了です。これにより、確認するオプションが表示されずにすべての一致が置き換えられるため、あまり気に入らない場合があります。もちろん、あなたはそれを

    nnoremap <leader>r yiw:%s/\<<C-r>"\>//gc<left><left><left>
    

    確認オプションを許可します。

    編集ミサの答えrcorreのコメント両方に続いて、これを次のように書くこともできます

    nnoremap <leader>r :%s/\<<C-r><C-w>\>//g<left><left>
    

    これには、名前のないレジスタを同じに保つという利点があります。

  2. 同様の変数のグループの名前を同時に変更する場合、たとえば、

    fooSuffix
    PrefixFoo
    foo1
    SHOUTINGFOO
    

    barSuffix
    PrefixBar
    bar1
    SHOUTINGBAR
    

    それらすべてを個別に置き換えるのは苦痛です。これは、tpope / vim-abolish役立つ場所です。これらすべてを1つのコマンドで次のように置き換えることができます。

    :%S/foo/bar/g
    

    そして、あなたのために大文字の世話をします。

これらはあなたを大いに助けてくれるはずですが、これらのアプローチについて、あなたが気に入らない、または足りないと感じているものがあれば教えてください。さらに多くのアプローチについてお話しできることを嬉しく思います。:)


推奨読書:


ああ、私はここでいくつかのことを学びました。いいね!あなたが取ることができる別のアプローチは、<leader>rc(またはcr/c最後にそれを追加することです。また、set gdefault設定したのは、1つの結果を置き換えることはほとんどないためです。したがって、それは単に yiw:%s/\<<C-r>"\>//<left><left>
Wayne Werner

2
なんて素晴らしい答えでしょう!
スコットルンドバーグ

2
ctrl+r-ctrl+wマッピングで使用する場合(@Massによって示唆されているように)、同じように機能しますが、ヤンクレジスタを混乱させません(望ましい場合もそうでない場合もあります)
rcorre

1
ハイライトしたテキストのブロックを操作するとき(カット/ヤンクなどの前)に覚えておくべきことの1つは、gvを通常モードで入力して、最後にハイライトしたテキストを再度ハイライトできることです。

1
方法2と同様に機能するgithub.com/hauleth/sad.vimプラグインを作成しました。hovewerを使用.して、さらに置換を実行できます。
Hauleth

20

c_CTRL-Rマップの家族はあなたのワークフローかなり向上させることができます。

  1. :s/使用CTRL-R CTRL-Wする場合、変数名を入力する必要はありません。カーソルの下の単語をコマンドラインに挿入するために使用します(注意:これは、特殊文字をエスケープしません*)。

  2. を使用して小さな変更を行った後ce、を使用して古い単語を検索できます/ CTRL-R -。次に、を使用.して変更を繰り返します。

  3. 検索パターンCTRL-R /を変更する必要がある場合は、既存の検索をコマンドラインに配置します。

  4. 最後に、次のコマンドを使用して任意のレジスタの内容を配置できます。 CTRL-R {register}


いい視点ね!私は常にCtrl Rを忘れます。私もそれを使用できるかどうかを確認します。
ジョエル

2
具体的に言及する価値はありCtrl-R /ますか?前の:s用語とほとんど同じですが、まったく同じではない検索用語を使用する場合、コマンドでこれを非常に頻繁に使用します。
リッチ

12

まだ言及されていない(驚いたことに)さらに2、3の方法があります。

gnコマンドを使用する

gnnコマンドと同様に機能しますが、マッチにジャンプすることに加えて、マッチ全体が選択された状態で視覚モードに入ります。

だから、単語を変更する(または何か、あなたは正規表現と一致させることができます!)最初にそれを検索1、次にキーを押しますcgnあなたが試合を交換すると、テキストが続きEsc、通常モードに戻ります。

(使用したい置換テキストが"0yankレジスタに保存される場合があることに言及しCtrl+R0ます。挿入モードで押すことにより、再入力せずにすばやく入力できることに注意してください。)

あなたは、次の試合にジャンプすることができますし、単一で変更を繰り返して.キーストローク!

置換を行いたくない場所がある場合、を押しunて変更を元に戻し、次の一致にジャンプします。

1:迅速には、のようなこのページ上の他の提案を使用することによって*Ctrl+RCtrl+Wなども参照のピーターRinckerのコメントを最初に検索を移入する方法については提案を。

選択モードを使用する

(これはvimain subredditに関するromainl投稿から学びました。彼がそれを自分で発明したのか、それを単に伝えただけなのかわかりません。)

選択モードは視覚モードに少し似ていますが、選択したテキストの入力を開始すると、入力した内容にすぐに置き換えられます(他のほとんどのエディターでの選択の動作など)。

したがって、この3つのマッピングを使用して、必要に応じて中間ファイルを変更できる非常に迅速な検索/置換を実行できます。

nnoremap § *``gn<C-g>
inoremap § <C-o>gn<C-g>
snoremap <expr> . @.

ノーマルモードマッピング:選択されたカーソルに最も近い単語で選択モードに入ります。

その後、選択した単語の置換を入力し、(押さずにEsc)以下を使用できます。

挿入モードマッピング:次の一致にジャンプし、選択モードに入ります。

次に、新しい置換を入力するか、を押して次.を使用できます。

モードマッピングの選択:最後に挿入されたテキストを再入力します—基本的に、最後の挿入を繰り返します。


昨日のgn回答vi.stackexchange.com/a/13696/488の最後でこの方法について言及しましたが、その価値は何ですか。あなたの答えは、はるかに優れたフォーマットを持っています。
TankorSmash

1
@TankorSmashでした!私がそれを見逃した方法を確認してください。私が使用している実際のメソッドはあなたのものとは異なりますが(私はgn一度だけ呼び出す)、それは特定のメソッドであることに注意してください(gnコマンドではなく)私はまだ言及されていなかったことに驚いていました。
リッチな

私が持っ推薦するいくつかの種類「ビジュアル・スター」で使用するプラグインをgn。より多くの検索オプションを提供します。貧乏人の視覚的な星のマッピング:xnoremap * :<c-u>let @/=@"<cr>gvy:let [@/,@"]=[@",@/]<cr>/\V<c-r>=substitute(escape(@/,'/\'),'\n','\\n','g')<cr><cr>。関連Vimcastsエピソード:gnを使用した検索マッチの操作
Peter Rincker

1
このようなフローを支援するプラグインsad.vimを作成しました。
Hauleth

7

プラグインhttps://github.com/terryma/vim-multiple-cursorsは、この問題の大部分を処理します。

私のワークフローは通常次のとおりです。

  1. 置換する単語にカーソルを移動します。
  2. ctrl-nすべてが選択されるまで押し続けます。
  3. を押してc、置換の入力を開始します。

ここで便利なのは、検索と置換だけでなく、より複雑な操作も行えることです。ただし、あまりにも遠くまで行けば、プラグインがいくつかの不具合を示し始めることがわかります。


4

まだ言及されていないことを行う別の方法:コマンドラインウィンドウ(q:通常モードで開きます-詳細:help q:を参照)を使用できます。このウィンドウでは、Vimのオートコンプリート機能(i_CTRL-N/ i_CTRL-Pおよびさまざまなi_CTRL-Xシーケンスに完全にアクセスできます)それらの中にあります)。

コマンドラインウィンドウでは、通常モードのコマンドを使用してコマンドラインを編集することもできます。これは、たとえば、コマンドライン履歴の以前のコマンドの一部をヤンクアンドペーストできることを意味します。

カーソルを使用すると、カーソルがコマンドラインウィンドウに移動しCTRL-R CTRL-Wます。つまり、通常のコマンドラインとは異なり、カーソルの下にテキストを挿入するなどの方法は機能しません。


1
また、途中であなたの入力によってすでにしているコマンドラインウィンドウを開くことができます:substitute押してコマンドを<ctrl-f>
リッチ

2

これに対する解決策は、私にとって他の答えの中間にあります。

6行の同一の行があり、真ん中の2行の「リンゴ」を置き換えるとします。

I have apples for days
I have apples for days
I have apples for days
I have apples for days
I have apples for days
I have apples for days

私がやることは:

  1. 置き換えるテキスト「apple」の先頭に到達します
  2. ヒットvして視覚モードに入る
  3. 私が置き換えたい最後の単語、この場合は数行に行きます 2j
  4. :s/<C-R><C-W>/の選択範囲を視覚的な選択範囲として使用し:s、カーソルの下に単語を挿入します
  5. ヒット<C-F>すると、コマンドをバッファであるかのように編集できるモードになります。したがって、置換語を選択するための補完またはプラグインは何でも使用でき、これで完了です。

すべて一行で、これに対するフローはそうなるでしょうが/apples<CR>2nv/apples<CR>nn:s/<C-R><C-W/oranges<CR>、それはそれよりも悪く見えます。

あなたの場合、範囲にスキップしたいものが含まれている場合は/c:sコマンドにを追加して不要なものをスキップできます::s/<C-R><C-W/orange/c

代わりに(そしておそらくより簡単に)、あなたは、交換したい単語全体を検索可能性がありc、その後、それをハンゲgnして.検索を繰り返して、再び同じ変更を適用します。/\<apple\><CR>viwcorange<ESC>gn.gn.gn..ngn.3回繰り返して、インスタンスをスキップして、最後に1回繰り返すように見えます。


最後に説明したメソッドは、私にとっては機能しません(Vim 7.4で呼び出されますvim -Nu NONE)。最初のボタンを押すとビープ音がし.ます。なぜそうなったのでしょうか?いずれにせよ、この方法で変更を行うciw代わりにviwn代わりに使用する方が簡単gnです。
リッチな

2

これは質問に完全に関連しているわけではありませんが、置換する単語を選択するのに役立つはずです。

インクリメンタル検索(set incsearch)を使用すると、検索する必要のある単語のプレフィックスを入力できます。vimは、入力するたびにプレフィックスの最初の出現箇所に自動的にジャンプします。Enterキーを押してEscで破棄すると、検索が確認されます(後者の場合、カーソルは検索開始前の場所に戻ります)。

ただし、インクリメンタル検索にはもう1つの便利な機能があります。既に単語のプレフィックスを入力し、カーソルが正しい位置にある場合、を押し<C-L>てカーソルの下の単語の文字を検索文字列に追加します。これにより、キーストロークをほとんどせずに、置換された文字列を入力できます。

だから、私は交換したい場合someOddVariableNameevenOdderVariableName、I

  1. を入力/someOddVして、出現するsomeOddVariableName;
  2. 検索行に完全に表示さ<C-L>れるまで押し続けsomeOddVariableNameます。
  3. Enterキーを押して検索を確認します。
  4. :%s//evenOdderVariableName/gまたは必要な置き換えコマンド。ここで他の回答に従うことをお勧めします。

2

あなたは(第1のバッファに変数名を入れることができますywし、それをコピー&ペースト単語をコピーする):%s押すことで<C-r>"


2

新しい(貼り付けられた)ブロック内の変数を置き換える場合、2つの提案があります。

自動交換

  • 新しいブロックの最初の行に移動して、を押しmaます。これは、場所をマークして名前を付けていaます。

  • 新しいブロックの最後の行に移動して、を押しmbます。これで、2つの名前付き場所ができました。

  • 次のように、2行の間を置き換えます :'a,'bs/oldVarName/newVarName/g

  • つまり、置換の範囲は2つのマークの間にあります。

手動の方法

  • 新しいブロックの最初の行に移動します。

  • を使用/oldVarNameして、の最初のインスタンスを見つけますoldVarName

  • 次のように変更します: cwnewVarName<Esc>、単語を変更しnewVarName、エスケープします。

  • を使用nして、の次のインスタンスに移動しますoldVarName

  • を使用.して、最後の変更を繰り返します(つまり、繰り返しますcw)。


2

ここでのその他の回答の多くは、検索と置換のワークフローを改善するための組み込みの方法をすでにカバーしていますが、Tim Popeのプラグインであるabolish.vimに言及したかったのです。通常、大文字小文字の違いや、単数形と複数形の両方の単語を処理する必要があるために、より広い範囲のケースをカバーしたい場合に置換を行います。

:S/child{,ren}/adult{,s}/g正しく変換childするadultChildrenAdultsCHILDしますADULT

キャメルケースの単語を処理する場合は、元の単語と置換単語に必要な大文字を含める必要があります。

%:S/wordWrap/textBreak/gwordWrapとの両方を正しく処理しwordwrapます。


0

他の人がすでに指摘したように、カーソルを単語の上に置いた場合、Ctrl + rコマンドファミリを使用できます。Ctrl+ r Ctrl + wがおそらく最も適しています。

ただし、その方法は1つの単語(カーソルのすぐ下)を挿入する場合にのみ機能しますが、使用するバッファ内のテキストのいくつかの部分がある場合はどうでしょうか。コマンドラインでカーソルを移動することはできません。これを行う最良の方法は、必要なテキストの部分を別のレジスターにコピーすることです。コピー演算子の前に「{reg_letter}(レジスターからの引用符と文字)を付けることにより、これを行うことができます。後でCtrl + r {reg_letter}を使用して、コマンドラインにさまざまな単語を挿入します。

しかし、前のアイデアに戻って、パターンの書き込み中にカーソルの位置をバッファ上で移動するといいでしょう。:私はちょうどことをしたプラグインを作成してそのように私たちは、Ctrlキー+ RはCtrl +と異なる位置ワットからのテキストを「選ぶ」ことができEXtend.vim プラグインはまた、置換操作を行うために多くの他の機能を持っています。

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