[search] Vim에서 전역 검색 및 바꾸기, 커서 위치에서 시작하여 둘러싸 기

/ 일반 모드 명령으로 검색 할 때 :

/\vSEARCHTERM

Vim은 커서 위치에서 검색을 시작하고 아래쪽으로 계속해서 위쪽으로 래핑합니다. 그러나 :substitute명령을 사용하여 검색하고 바꿀 때 :

:%s/\vBEFORE/AFTER/gc

대신 Vim은 파일 상단에서 시작합니다.

빔 검색 및 커서 위치에서 시작하여 대체 실시합니다 만들 수있는 방법이 그 끝에 도달 한 번 정상에 주변의 포장은?



답변

1.  2 단계 대체를 사용하여 동작을 달성하는 것은 어렵지 않습니다.

:,$s/BEFORE/AFTER/gc|1,''-&&

먼저, 현재 행에서 시작하여 파일 끝까지 각 행에 대해 대체 명령이 실행됩니다.

,$s/BEFORE/AFTER/gc

:substitute 명령을 사용하여 동일한 검색 패턴, 대체 문자열 및 플래그를 사용하여 명령을 반복합니다 :& (참조 :help :&).

1,''-&&

그러나 후자는 파일의 첫 번째 행에서 이전 컨텍스트 표시가 설정된 행까지의 행 범위에서 1을 뺀 범위에서 대체를 수행합니다. 처음부터:substitute 명령은 실제 ​​대체를 시작하기 전에 커서 위치를 저장 주소  ''가 지정된 행은 대체 명령이 실행되기 전에 현재 행이었던 행입니다. ( '' 주소는 ' 의사 표시를 나타냅니다
. 자세한 내용 은 :help :range및 참조 :help '')

두 번째 명령 ( | 명령 구분 기호 뒤 — 참조
:help :bar)은 첫 번째 명령 에서 패턴 또는 플래그가 변경 될 때 변경이 필요하지 않습니다.

2.  타이핑을 저장하기 위해 명령 줄에서 위의 대체 명령의 골격을 가져 오기 위해 다음과 같이 일반 모드 매핑을 정의 할 수 있습니다.

:noremap <leader>cs :,$s///gc\|1,''-&&<c-b><right><right><right><right>

후행 <c-b><right><right><right><right> 부분은 커서를 명령 줄의 시작 부분 ( <c-b>)으로 이동 한 다음 오른쪽으로 4 자 ( <right> × 4)로 이동하여 처음 두 개의 슬래시 기호 사이에 배치하여 사용자가 검색 패턴을 입력 할 수 있도록하는 데 필요합니다. . 원하는 패턴과 교체가 준비되면을 눌러 결과 명령을 실행할 수 있습니다
Enter.

( 위의 매핑 //대신에 ///패턴을 입력하는 것을 선호하는 경우 오른쪽 화살표를 사용하여 커서를 이미 존재하는 분리 슬래시 시작 위로 이동하는 대신 분리 슬래시를 직접 입력 한 다음 대체 문자열을 입력하는 것을 고려할 수 있습니다. 교체 부품.)


답변

이미 전체 파일 %1,$의미하는 약칭 인 범위를 사용하고 있습니다. 현재 줄에서 끝으로 이동하려면을 사용 .,$합니다. 마침표는 현재 줄을 $의미하고 마지막 줄을 의미합니다. 따라서 명령은 다음과 같습니다.

:.,$s/\vBEFORE/AFTER/gc

그러나 .또는 현재 행을 가정 할 수 있으므로 제거 할 수 있습니다.

:,$s/\vBEFORE/AFTER/gc

더 많은 도움이 필요하면

:h range


답변

%1,$
(Vim help => :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)


답변

다음 은 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

이 함수는 몇 가지 해킹을 사용하여 맨 위로 돌아 가야하는지 확인합니다.

  • 사용자가 “l”, “q”또는 “Esc”를 눌렀을 때 줄 바꿈을하지 않습니다.이 중 어느 것이 든 중단하려는 것을 나타냅니다.
  • “s”레지스터에 매크로를 기록하고 마지막 문자를 검사하여 마지막 키 누름을 감지합니다.
  • “s”레지스터를 저장 / 복원하여 기존 매크로를 덮어 쓰지 마십시오.
  • 명령을 사용할 때 이미 매크로를 기록하고 있다면 모든 베팅이 해제됩니다.
  • 인터럽트로 올바른 일을하려고합니다.
  • 명시적인 가드로 “뒤로 범위”경고를 피합니다.

답변

나는 파티에 늦었지만 그렇게하지 않기 위해 그렇게 늦은 스택 오버플로 응답자에게 너무 자주 의존했습니다. reddit 및 stackoverflow에 대한 힌트를 수집했으며 가장 좋은 방법은 \%>...c검색 에서 패턴 을 사용하는 것입니다.이 패턴은 커서 이후에만 일치합니다.

즉, 다음 교체 단계에서 패턴을 엉망으로 만들고 입력하기가 어렵습니다. 이러한 효과에 대응하기 위해 사용자 지정 함수는 나중에 검색 패턴을 필터링하여 재설정해야합니다. 아래를 참조하십시오.

나는 다음 발생을 대체하고 그 이후에 다음으로 점프하는 매핑으로 자신을 다 투었습니다 (어쨌든 내 목표였습니다). 나는 이것을 기반으로 글로벌 대체가 이루어질 수 있다고 확신합니다. :%s/.../.../g아래 패턴이 일치 항목을 필터링하는 것과 같은 것을 목표로하는 솔루션을 작업 할 때 유의 하세요. 이 커서 위치에 남아 모든 행 그러나 단일 대체가 완료된 후에 정리되므로 바로 그 효과를 잃고 다음 경기이므로 모든 경기를 하나씩 진행할 수 있습니다.


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


답변