원래 단어를 입력하지 않고 Vim에서 찾아서 바꾸는 방법은 무엇입니까?


53

Vim에서 "찾기 및 바꾸기"워크 플로를 최적화하고 싶습니다. 대부분의 사람들도 그렇듯이 자주하는 일입니다. 일반적으로 라인을 따라 무언가- 블록을 복사하고 몇 곳에서 변수 이름을 변경하십시오. 나는 아마도 "당신은 왜 코드를 복사하고 붙여 넣는가"반사를 유발할지도 모른다는 것을 알고 있습니다. 그러나 그 길로 내려 가지 마십시오 ...

나는 검색을 잘 알고 있어요와 명령을 바꾸 :s거나 :%s하지만 난 그들을 좋아하지 않는다. 검색중인 전체 변수 이름과 변경하려는 이름을 모두 입력해야합니다. 으로 입력 양을 수정하는 더 좋은 방법이 :%s있습니까? 나는 종종 긴 설명 변수 이름을 사용하므로 실제로 나를위한 거래 차단기입니다. 또한 처음부터 변수 이름을 입력하는 것이 오타하기 쉽고 오타를 제거하는 데 시간과 두뇌를 소모하는 방법이 마음에 들지 않습니다. 한 번 입력 한 다음 복사하고 붙여 넣기를 사용하여 가능한 경우이를 완전히 피하는 것이 좋습니다.

현재의 워크 플로는 이동 / 잉크 / 선택 / 검색 / 입력 조합을 사용하여 파일을 이동하고 하나씩 교체합니다. 훌륭하지는 않지만 전체 변수 이름을 입력하지 않는 이점이 있습니다. 주위의 내용에 따라 처음 몇 글자를 입력 /하거나 다른 이동 명령 (예 :)을 사용해야 할 수도 있습니다 . 또한 모든 인스턴스에 대해 반복해야한다는 것을 신경 쓰지 않습니다. 각 변경 사항을 확인하지 않고 찾기를 완전히 수행하지는 않습니다. 그러나 단일 키 입력 (이 방법으로는 할 수없는)으로 교체 작업을 반복 할 수 있다면 훨씬 바람직합니다. 각각의 교체와 같은 일반적으로 뭔가 후 다음 (또는 더 나쁜 )fxvenvep"0p

더 빠른 방법이 있습니까?


1
.마지막 "명령 블록"을 반복합니다 (정확한 용어는 확실하지 않습니다 (예 : 이동 + 동작 + 텍스트). 예 : cwtoto<Esc>(커서에서 "toto"로 단어의 끝으로 c/foo<enter>bar<Esc>변경 ), (커서에서 "직전으로 변경" foo "로 바꾸고"bar "로 바꿉니다. 그런 다음 커서, hjkl 또는 숫자 + hjkl (n 번 수행), G (파일 끝으로 이동), / something (" )를 누른 다음을 눌러 .동일한 "명령 블록"을 다시 실행하십시오
Olivier Dulac

나는 이것을 꽤 많이 사용합니다! 그러나 단어를 잡아 당기고 여러 장소에서 다른 단어로 바꾸려면 작동하지 않습니다. 그것이 문제가있는 주요 유스 케이스이며 다음과 같습니다 n ve "0p. 불행히도 다음과 같이 복제 할 수 없습니다.
Joel

5
n ce ctrl-r 0 <esc> n.n.n.n.n.n.
Rich

@Joel 또한 매크로를 기록 할 수 있습니다 (qa, 원하는 모든 것, q : 매크로 a 생성) .: @a를 사용하여 재생합니다 (일반적으로 134 @ a는 134 회 수행). 매크로는 필요에 따라 정교하게 만들 수 있습니다 (예 : 무언가를 찾고 적절한 장소로 이동 한 다음 단어를 그 위치로 변경 한 다음 더 나은 위치에서 다시 호출 할 수 있도록 적절한 장소로 이동)
Olivier Dulac

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. 그러면 교체 여부를 결정하기 위해 각 경우에 입력 y하거나 입력 할 수 있습니다 n.

    으로 Desty 지적 , 당신은 또한 할 수있는 &마지막 대체 명령을 다시 실행하지만,이 점에 유의 할 수 없습니다 귀하의 플래그를 (예 : 유지 global또는 confirm). 그것이 좋은지 나쁜지는 개인적인 의견에 달려 있습니다. 이것을 사용하고 싶지만 플래그도 유지하려면 할 수 있습니다

    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>
    

    확인 옵션을 허용합니다.

    편집 : Mass의 답변rcorre의 의견에 따라 다음 과 같이 작성할 수도 있습니다.

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

    명명되지 않은 레지스터를 동일하게 유지하는 이점이 있습니다.

  2. 비슷한 변수 그룹을 동시에 이름을 바꾸는 경우 (예 : 변경)

    fooSuffix
    PrefixFoo
    foo1
    SHOUTINGFOO
    

    barSuffix
    PrefixBar
    bar1
    SHOUTINGBAR
    

    그것들을 모두 개별적으로 대체하는 것은 고통이 될 수 있습니다. 이것은 tpope / vim-abolish 가 유용한 곳입니다. 하나의 명령으로 이들을 모두 다음으로 바꿀 수 있습니다.

    :%S/foo/bar/g
    

    그리고 그것은 당신을 위해 대문자를 처리합니다.

이것들은 당신에게 많은 도움이 될 것입니다. 더 많은 접근법에 대해 이야기하게되어 기쁩니다. :)


추천 자료 :


아, 방금 여기서 몇 가지를 배웠습니다. 좋은! 당신이 취할 수있는 대안은 <leader>rc(또는 cr) /c끝에 추가하는 것 입니다. 또한, 나는 set gdefault하나의 단일 결과를 거의 바꾸고 싶지 않기 때문에 설정했습니다. yiw:%s/\<<C-r>"\>//<left><left>
Wayne Werner

2
정말 멋진 답변입니다!
Scott Lundberg

2
ctrl+r-ctrl+w매핑에서 사용하는 경우 (@Mass에서 제안한대로) 동일하게 작동하지만 (양호한 수도 아닐 수도있는)
양각

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을 잊어 버린다. 나도 그 일을 할 수 있는지 볼 것이다.
Joel

2
특별히 언급 할 가치가 Ctrl-R /있습니까? 이전 :s키워드와 거의 같지만 정확히 일치하지 않는 검색어를 사용하려는 경우 명령 에서이를 자주 사용합니다.
Rich

12

아직 놀랍지 않은 방법이 몇 가지 더 있습니다.

gn명령 사용

gnn일치하는 항목으로 이동하는 것 외에도 전체 일치 항목이 선택된 상태로 시각적 모드로 전환된다는 점을 제외하고 명령과 동일하게 작동합니다 .

그래서 단어를 변경 (또는 아무것도 당신은 정규 표현식과 일치시킬 수 있습니다!) 그것을위한 첫 번째 검색 1 키를 누릅니다, 그리고 cgn당신이 경기를 교체하고 원하는 텍스트 다음에 Esc일반 모드로 돌아갑니다.

(사용하려는 대체 텍스트가 "0yank 레지스터에 저장되는 경우가 있습니다 Ctrl+R0. 삽입 모드 에서을 눌러 다시 입력하지 않고도 빠르게 입력 할 수 있습니다 .)

그런 다음 다음 경기로 이동할 수 단일로 변경을 반복 .키 입력!

교체하고 싶지 않은 곳이있는 경우 ,를 눌러 un변경을 취소하고 다음 경기로 넘어갑니다.

1 :이 페이지 *에서 Ctrl+RCtrl+W, 등 의 다른 제안을 사용하여 신속하게 검색합니다. 처음에 검색을 채우는 방법에 대한 자세한 제안은 Peter Rincker의 의견 도 참조하십시오 .

선택 모드 사용

(나는 vim subreddit 에 대한 romainl게시물 에서 이것을 배웠다 . 그가 그것을 스스로 발명했는지 아니면 그냥 전달했는지는 모른다.)

선택 모드는 입력을 시작하면 선택한 텍스트가 즉시 입력 한 텍스트로 대체됩니다 (대부분의 다른 편집기에서 선택이 작동하는 방식).

따라서이 트리오 매핑을 사용하여 매우 빠른 찾기 / 바꾸기를 수행 할 수 있으며 필요한 경우 중간 파일을 변경할 수 있습니다.

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내가 놀랐던 특정 방법 ( 명령이 아닌 )은 아직 언급되지 않았습니다.
Rich

나는 가진 것이 좋습니다 어떤 종류"시각적 스타" 와 함께 사용하는 플러그인 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>
Rich

2

이것에 대한 해결책은 다른 대답 사이에 있습니다.

6 개의 동일한 줄이 있고 가운데 2 개에서 'apple'을 바꾸고 싶다고 가정 해보십시오.

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다음, hange을 gn하고 .검색을 반복하고 다시 같은 변경 사항을 적용 할 수 있습니다. /\<apple\><CR>viwcorange<ESC>gn.gn.gn..ngn.세 번 반복 한 다음 인스턴스를 건너 뛰고 마지막으로 한 번 반복하는 것처럼 보입니다 .


마지막에 설명하는 방법이 저에게 효과적이지 않습니다 (Vim 7.4에서는로 호출 vim -Nu NONE). 첫 번째를 누르면 경고음이 울립니다 .. 왜 그런지 아십니까? 어떤 경우에는, 사용하기 간단 것 ciw대신 viw하고 n대신 gn이 방법을 변경할 수 있습니다.
Rich

2

이것은 전적으로 질문과 관련이 없지만 대체 할 단어를 선택하는 데 여전히 도움이됩니다.

증분 검색 ( set incsearch)을 사용하면 찾으려는 단어의 접두사를 입력 할 수 있으며 vim은 점점 더 많이 입력 할 때 접두사의 첫 번째 항목으로 자동 이동합니다. Esc에서 Enter 키를 누르고 버린 경우 검색이 확인됩니다 (후자의 경우 검색이 시작되기 전의 위치로 커서가 이동 함).

그러나 증분 검색은 하나 더 유용한 기능을 제공합니다. 단어의 접두사를 이미 입력 한 상태에서 커서가 올바른 위치에 있으면 <C-L>커서 아래 단어의 단어를 검색 문자열에 추가하려면을 누릅니다 . 이를 통해 거의 키를 입력하지 않고 교체 된 문자열을 입력 할 수 있습니다.

그래서, 교체 할 경우 someOddVariableNameevenOdderVariableName, I

  1. 입력 /someOddV하고 발생 someOddVariableName;
  2. 검색 줄에가 나타날 <C-L>때까지 길게 누릅니다 someOddVariableName.
  3. 검색을 확인하려면 Enter를 누르십시오.
  4. :%s//evenOdderVariableName/g또는 필요한 대체 명령; 여기에서 다른 답변을 따르고 싶을 수도 있습니다.

2

당신은 (첫 번째 버퍼에 변수 이름을 넣을 수 있습니다 yw에 단어를 복사하기 위해), 다음을 복사 - 붙여 넣기 :%s쳐서 <C-r>".


2

새로운 (붙여 넣은) 블록 내에서 변수를 바꾸려면 두 가지 제안이 있습니다.

자동 교체

  • 새 블록의 첫 번째 줄로 이동하여을 누르십시오 ma. 위치를 표시하고 이름을 지정합니다 a.

  • 새 블록의 마지막 줄로 이동하여를 누르십시오 mb. 이제 두 개의 명명 된 위치가 있습니다.

  • 이제 다음 과 같이 두 줄 사이를 교체하십시오 :'a,'bs/oldVarName/newVarName/g.

  • 즉, 교체 범위는 두 마크 사이입니다.

수동 방법

  • 새 블록의 첫 번째 줄로 이동하십시오.

  • /oldVarName의 첫 번째 인스턴스를 찾는 데 사용하십시오 oldVarName.

  • 다음과 같이 변경하십시오 :. cwnewVarName<Esc>단어가 변경 newVarName되고 이스케이프가 발생합니다.

  • n다음 인스턴스로 이동하는 데 사용 합니다 oldVarName.

  • .마지막 변경을 반복하는 데 사용 합니다 (예 :) cw.


2

여기에있는 다른 많은 답변은 이미 찾기 및 바꾸기 워크 플로우를 향상시키는 내장 방법을 다루고 있지만 Tim Pope의 플러그인 abolish.vim 을 언급하고 싶었습니다 . 일반적으로 경우에 따라 변형되거나 단수형과 복수형의 단어를 모두 처리해야하므로 더 넓은 범위의 사례를 대체하려는 경우 대체합니다.

:S/child{,ren}/adult{,s}/g올바르게 변환 childadult, ChildrenAdultsCHILDADULT.

낙타의 경우 단어를 다루는 경우 원래의 단어와 대체 단어에서 필요한 곳에 대문자를 포함시켜야합니다.

%:S/wordWrap/textBreak/g올바르게 모두 처리 wordWrap하고 wordwrap.


0

이미 지적했듯이 커서를 단어 위에 놓으면 Ctrl + r 명령 계열을 사용할 수 있으며 Ctrl + r Ctrl + w가 가장 적합합니다.

그러나이 방법은 한 단어 (커서 바로 아래에있는 단어) 만 삽입하는 데 효과적이지만 버퍼에 몇 개의 텍스트 부분이있는 경우 어떻게해야합니까? 명령 행에서 커서를 움직일 수 없습니다. 이 작업을 수행하는 가장 좋은 방법은 필요한 텍스트 부분을 다른 레지스터로 복사하는 것입니다. 접두사 "{reg_letter} (따옴표 및 레지스터의 문자)를 복사 연산자 앞에 붙여서 수행 할 수 있습니다. 나중에 Ctrl + r {reg_letter}를 사용하여 명령 줄에 다양한 단어를 삽입하십시오.

그러나 이전 아이디어로 돌아가서 패턴을 쓰는 동안 커서 위치를 버퍼 위로 이동하면 좋을 것입니다. 이렇게하면 Ctrl + r Ctrl + w를 사용하여 다른 위치에서 텍스트를 "선택"할 수 있으므로 다음과 같은 플러그인을 만들었습니다. EXtend.vim 플러그인에는 대체 작업을 수행 할 수있는 다른 기능도 많이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.