で検索するとき
/\vSEARCHTERM
Vimはカーソル位置から下に向かって検索を開始し、上に折り返します。ただし、検索と置換を使用して
:%s/\vBEFORE/AFTER/gc
Vimはファイルの先頭から始まります。
Vimをカーソル位置から検索して置換し、最後に到達したら先頭に折り返す方法はありますか?
2段階の置換を使用して動作を実現するのは難しくありません。
:,$s/BEFORE/AFTER/gc|1,''-&&
最初に、現在の行からファイルの終わりまでの各行に対して置換コマンドが実行されます。次に、:substitute
コマンドを使用して、同じ検索パターン、置換文字列、およびフラグを使用して、その:&
コマンドを繰り返します。ただし、後者は、ファイルの最初の行から前のコンテキストマークが設定されている行から1を引いた行までの行の範囲で置換を実行します。最初の:substitute
コマンドは実際の置換を開始する前にカーソル位置を保存するため、''
でアドレス指定された行は、その置換コマンドが実行される前の現在の行でした。
2番目のコマンド(|
シンボルの後)は、最初のコマンドまたはパターンのフラグが変更されたときに変更を必要としないことに注意してください。
既に%
の範囲を使用しています。これは、ファイル全体を意味する1,$
の省略形です。現在の行から最後まで移動するには、.,$
を使用します。ピリオドは現在の行を意味し、$
は最後の行を意味します。したがって、コマンドは次のようになります。
:.,$s/\vBEFORE/AFTER/gc
ただし、.
または現在の行は想定されるため、削除できます。
:,$s/\vBEFORE/AFTER/gc
詳細については
:h range
%
は1,$
のショートカットです
(Vimヘルプ=> :help :%
は1、$(ファイル全体)に等しい。)
.
はカーソル位置であるため、次のことができます。
:.,$s/\vBEFORE/AFTER/gc
ドキュメントの先頭からカーソルまでを置換するには
:1,.s/\vBEFORE/AFTER/gc
等
ほぼすべてのコマンドが範囲で機能するため、範囲:help range
に関するマニュアルを読むことを強くお勧めします。
私は最終的に、膨大な関数を作成せずに検索を終了するとファイルの先頭に戻るという事実の解決策を思い付きました...
あなたは私がこれを思い付くのにどれくらい時間がかかったかを信じないでしょう。単にラップするかどうかを確認するプロンプトを追加します。ユーザーがq
を再度押してもラップしないでください。基本的に、qq
の代わりにq
をタップして検索を終了します! (そして、ラップしたい場合は、単にy
と入力してください。)
:,$s/BEFORE/AFTER/gce|echo 'Continue at beginning of file? (y/q)'|if getchar()!=113|1,''-&&|en
私は実際にこれをホットキーにマッピングしています。したがって、たとえば、現在の位置からカーソルの下のすべての単語を検索してq*
に置き換える場合:
exe 'nno q* :,$s/\<<c-r>=expand("<cword>")<cr>\>//gce\|echo "Continue at beginning of file? (y/q)"\|if getchar()==121\|1,''''-&&\|en'.repeat('<left>',77)
私はパーティーに遅れていますが、そうしないために、このような遅いstackoverflow answerrsに頼りすぎました。 redditとstackoverflowに関するヒントを集めましたが、最適なオプションは、カーソルの後にのみ一致する_\%>...c
_パターンを検索で使用することです。
そうは言っても、次の置換ステップのパターンを台無しにし、入力するのは困難です。これらの効果に対抗するには、カスタム関数は後で検索パターンをフィルタリングして、リセットする必要があります。下記参照。
私は次の出来事に取って代わり、それ以降ではなく次の事柄にジャンプするマッピングで自分自身と競合しました(とにかく私の目標は)。私はこれに基づいて、グローバルな代替が解決できると確信しています。 _:%s/.../.../g
_のようなものを目指してソリューションを作成する場合は、以下のパターンがallカーソル位置までの行を除外しますが、単一の置換が完了するとクリーンアップされることに注意してください、そのため、その効果はすぐに失われ、次のマッチにジャンプして、すべてのマッチを1つずつ実行することができます。
fun! g:CleanColFromPattern(prevPattern) return substitute(a:prevPattern, '\V\^\\%>\[0-9]\+c', '', '') endf nmap <F3>n m`:s/\%><C-r>=col(".")-1<CR>c<C-.r>=g:CleanColFromPattern(getreg("/"))<CR>/~/&<CR>:call setreg("/", g:CleanColFromPattern(getreg("/")))<CR>``n
以下は、検索を 2段階アプローチ (:,$s/BEFORE/AFTER/gc|1,''-&&
)または中間 "ファイルの先頭で続行しますか?" アプローチ:
" Define a mapping that calls a command.
nnoremap <Leader>e :Substitute/\v<<C-R>=expand('<cword>')<CR>>//<Left>
" And that command calls a script-local function.
command! -nargs=1 Substitute call s:Substitute(<q-args>)
function! s:Substitute(patterns)
if getregtype('s') != ''
let l:register=getreg('s')
endif
normal! qs
redir => l:replacements
try
execute ',$s' . a:patterns . 'gce#'
catch /^Vim:Interrupt$/
return
finally
normal! q
let l:transcript=getreg('s')
if exists('l:register')
call setreg('s', l:register)
endif
endtry
redir END
if len(l:replacements) > 0
" At least one instance of pattern was found.
let l:last=strpart(l:transcript, len(l:transcript) - 1)
" Note: type the literal <Esc> (^[) here with <C-v><Esc>:
if l:last ==# 'l' || l:last ==# 'q' || l:last ==# '^['
" User bailed.
return
endif
endif
" Loop around to top of file and continue.
" Avoid unwanted "Backwards range given, OK to swap (y/n)?" messages.
if line("''") > 1
1,''-&&"
endif
endfunction
この関数は、いくつかのハックを使用して、先頭に折り返す必要があるかどうかを確認します。