Vim에서 모든 프로젝트 파일 검색 및 바꾸기


117

Vim의 모든 프로젝트 파일에서 검색 및 바꾸기 (확인 포함)를 수행하는 가장 좋은 방법을 찾고 있습니다. "프로젝트 파일"이란 현재 디렉토리에있는 파일을 의미하며 일부는 열지 않아도됩니다.

이를 수행하는 한 가지 방법은 현재 디렉토리에있는 모든 파일을 여는 것입니다.

:args ./**

그런 다음 열려있는 모든 파일을 검색하고 바꿉니다.

:argdo %s/Search/Replace/gce

그러나 이렇게하면 Vim의 메모리 사용량이 수십 MB에서 2GB 이상으로 증가하여 저에게 적합하지 않습니다.

또한 EasyGrep 플러그인이 설치되어 있지만 거의 작동하지 않습니다. 모든 항목을 찾지 못 하거나을 누를 때까지 중단 CtrlC됩니다. 지금까지이 작업을 수행하기 위해 선호하는 방법 은 검색어에 대해 ack-grep하는 것 입니다. quickfix 창을 사용하여 이전에 열지 않은 용어가 포함 된 파일을 열고 마지막으로 :bufdo %s/Search/Replace/gce.

나는 이것을 위해 사용할 수있는 훌륭하고 작동하는 플러그인을 찾고 있거나, 아니면 내가 지금 사용하고있는 것보다 더 쉬운 명령 / 시퀀스를 찾고있다.


1
@Cascabel이 의견을 작성하신 이후로 vi.stackexchange.com 사이트가 있습니다.
Flimm

답변:


27

Greplace 는 나를 위해 잘 작동합니다.

github 에는 병원체 준비 버전 도 있습니다 .


8
그것을 설치하면 다른 명령이 :Gsearch있고 :Gbuffersearch존재 하는 것을 볼 수 있지만 입력 :Greplace하면 Not an editor command: Greplace.
Ramon Tayag 2011

문서에 따르면 구문은 다음과 같습니다. :Gsearch [<grep-option(s)>] [[<pattern>] [<filename(s)>]] 예를 들어 다음을 사용하여 재귀 검색을 수행 할 수 있습니다.:Gsearch -r pattern dir/
vitorbal

내가 Greplace에 대해 싫어하는 점은 패턴이 파일 이름에 있으면 Greplace가 실패한다는 것입니다. 그 이유는 파일 이름에서도 결국 대체되기 때문입니다.
Daniel

2
6 년이 지난 후에도이 플러그인은 3 년 이상 전의 최근 업데이트 ( github.com/yegappan/greplace ) 와 비교할 때 심각하게 구식입니다 . Sid의 내장 솔루션을 확인할 수 있습니다. stackoverflow.com/a/38004355/2224331 (다른 계정에있는 것이 아니라 우연의 일치입니다 : P)
SidOfc

99

여기서 또 다른 큰 옵션은 단순히 vim을 사용하지 않는 것입니다.

sed -i 's/pattern/replacement/' <files>

또는 파일 목록을 생성하는 방법이 있다면 다음과 같습니다.

find . -name *.cpp | xargs sed -i 's/pattern/replacement/'
grep -rl 'pattern1' | xargs sed -i 's/pattern2/replacement/'

등등!


감사! 이 오래된 학교 명령 줄에 대해 정말 배워야합니다. 이것이 최선의 답이라고 생각합니다. 이 정규식은 perl 정규식입니까, vim 정규식입니까, 아니면 다른 종류의 정규식입니까?
에릭 존슨

2
@EricJohnson : 그것들 sed은 본질적으로 POSIX.2 기본 정규식이지만 정확히는 (맨 페이지에 있음) 정규식 인 정규식 \n입니다. 따라서 grep정규 표현식 과 거의 동일 합니다.
Cascabel

sed 명령에 -i가있는 이유가 있습니까? 매뉴얼 페이지에는 확장을 지정하기위한 것이지만 실제로 지정하는 것처럼 보이지는 않습니다.
davekaro 2013

Ok 그것은 실제로 's / pattern / replacement /'가 확장 인 것처럼 보입니다. 이제 이해한다고 생각합니다.
davekaro 2013

11
Mac OS X에서 저에게 효과가 있었던 유일한 sed 명령은 다음과 같습니다.find . -type f | LANG=C xargs sed -i '' 's/SEARCH/REPLACE/g'
ghodss

74

편집 : cfdo대신 명령을 사용 cdo하여이를 수행하기 위해 실행할 명령의 양을 크게 줄입니다 ( 각 파일에서 명령 cdocfdo실행 하는 동안 각 요소에서 명령을 실행 하기 때문에 ).

최근에 추가 된 cdo명령 덕분에 이제 grep설치 한 도구를 사용하여 두 개의 간단한 명령으로이 작업을 수행 할 수 있습니다 . 추가 플러그인이 필요하지 않습니다! :

1. :grep <search term>
2. :cdo %s/<search term>/<replace term>/gc
3. (If you want to save the changes in all files) :cdo update

( 명령이 채워지 cdo는 빠른 수정 목록의 각 용어에 대해 주어진 명령을 실행합니다 grep.)

( c매번 확인하지 않고 각 검색어를 바꾸려면 두 번째 명령의 끝에서 제거 )


12
또한 :cdo update모든 파일의 변경 사항을 저장하기 위해 추가 할 수 있습니다 .
Zhe Li

1
그러나 현재 버퍼가 수정되면 다음 버퍼로 전환하기 전에 매번 저장되지 않음을 경고하기 위해 일시 ​​중지됩니다.
lfree

1
@Zhe 감사합니다, 나는 그것을 대답에 추가했습니다. @lfree 저는 개인적으로 각 변경 사항을 확인하는 것을 선호하지만 c두 번째 명령의 끝에서를 제거하여 g확인을 요청하지 않고 검색하고 교체하도록 할 수 있습니다.
Sid

1
: cdo % s / search term / replace term / g 첫 번째 항목 만 대체하지만 내 vim에서 두 번째 항목에는 작동하지 않습니다
sunxd

3
를 사용 update하기 위해 다음을 수행해야했습니다.cdo %s/<search term>/<replace term>/g | update
gabe

34

나는 GNU 하위 집합이 아닌 더 강력한 전체 Perl 정규식을 활용하기 위해이 문제를 해결하기 위해 ack 및 Perl을 사용하기로 결정했습니다.

ack -l 'pattern' | xargs perl -pi -E 's/pattern/replacement/g'

설명

확인

ACK는 (A)의 혼합이다 멋진 명령 줄 도구입니다 grep, find그리고 전체 펄 정규 표현식 (뿐만 아니라 GNU 부분 집합). 순수한 Perl로 작성되었으며 빠르며 구문 강조 기능이 있으며 Windows에서 작동하며 기존 명령 줄 도구보다 프로그래머에게 더 친숙합니다. Ubuntu에 sudo apt-get install ack-grep.

xargs

Xargs 는 오래된 유닉스 명령 줄 도구입니다. 표준 입력에서 항목을 읽고 지정된 명령 다음에 표준 입력을 위해 읽은 항목을 실행합니다. 따라서 기본적으로 ack에 의해 생성 된 파일 목록이 perl -pi -E 's/pattern/replacemnt/g'명령 끝에 추가됩니다 .

펄 -pi

Perl은 프로그래밍 언어입니다. -p 옵션은 Perl이 파일 이름 인수를 반복하는 프로그램 주위에 루프를 생성하도록합니다. -i 옵션은 Perl이 파일을 제자리에서 편집하도록합니다. 이를 수정하여 백업을 생성 할 수 있습니다. -E 옵션은 Perl이 프로그램으로 지정된 한 줄의 코드를 실행하도록합니다. 우리의 경우 프로그램은 Perl 정규식 대체 일뿐입니다. Perl 명령 줄 옵션에 대한 자세한 내용 perldoc perlrun. Perl에 대한 자세한 내용은 http://www.perl.org/를 참조 하십시오 .


이 답변은 cygwin의 라인 엔딩에서도 작동하기 때문에 좋아합니다. 수정 된 줄 끝에 \ r을 추가하지만 sed를 사용하면 모든 줄 바꿈 을 대체 하여 diff를 사용할 수 없게됩니다. Perl은 좀 더 제정신이며 이것은 검색 및 교체를위한 정말 훌륭한 한 줄입니다. 감사!
앤드류

@ 앤드류, 귀하의 경우에 무엇이 잘못되었는지 정확히 모르겠습니다. 정규 표현식에서 \ n 대신 \ R을 사용하는 것이 도움이됩니까? perldoc.perl.org/perlrebackslash.html#Misc의 \ R 섹션을 참조하세요 . 또한 perldoc.perl.org/perlre.html#Regular-Expressions를 사용 해보세요 . Perl은 극도로 교차 플랫폼이며 난 당신이 엉망이 된 라인 엔딩으로 끝나지 않을 방법이 있다고 확신합니다.
Eric Johnson

내 정규식에는 줄 바꿈이 없으며 이러한 프로그램의 cygwin 버전은 수정 된 각 줄 끝에 \ r을 자동으로 추가합니다. 펄 버전은 일치하는 줄만 수정하는 반면 sed는 정규식과 일치하지 않더라도 모든 줄을 수정하기 때문에 특별히 좋아했습니다 .
andrew

파일 경로에 공백이 있으면 어떻게됩니까?
shengy

23

아마도 이렇게 :

:noautocmd vim /Search/ **/*
:set hidden
:cfirst
qa
:%s//Replace/gce
:cnf
q
1000@a
:wa

설명:

  • :noautocmd vim /Search/ **/*⇒ 속도를 위해 autocmds ( ) 를 트리거하지 않고 cwd의 모든 하위 디렉토리에있는 모든 파일에서 패턴을 조회 ( vim는 약어 vimgrep임) :noautocmd합니다.
  • :set hidden ⇒ 수정 된 버퍼가 창에 표시되지 않도록 허용 (vimrc에있을 수 있음)
  • :cfirst ⇒ 첫 번째 검색 결과로 이동
  • qa 레지스터에 매크로 기록을 시작 ⇒
  • :%s//Replace/gce⇒ 마지막 검색 패턴의 모든 항목을 ( /Search/그 당시에도) 다음으로 바꿉니다 Replace.
    • 같은 줄에 여러 번 ( g플래그)
    • 사용자 확인 포함 ( c플래그)
    • 패턴을 찾을 수없는 경우 오류없이 ( e플래그)
  • :cnfvim명령에 의해 생성 된 목록에서 다음 파일로 이동
  • q ⇒ 매크로 기록 중지
  • 1000@a ⇒ 레지스터에 저장된 매크로를 1000 번 재생
  • :wa ⇒ 수정 된 모든 버퍼 저장

* 편집 * Vim 8 방법 :

Vim 8부터는 :cfdo빠른 수정 목록의 모든 파일 을 반복 하므로 더 나은 방법이 있습니다 .

:noautocmd vim /Search/ **/*
:set hidden
:cfdo %s//Replace/gce
:wa

당신은 좀 더 작은 필사자들에게 그것을 설명하고 싶을 것입니다. 매번이 "시퀀스"를 수행해야하는지 확실하지 않습니다. 나는 녹슨 오래된 Delphi 5를 사용하여 더 빨리 수행하므로 분명히 무언가를 놓치고 있어야합니다.
Lieven Keersmaekers 2011 년

1
@Lieven : 당신 말이 맞습니다, 이것은 코멘트 없이는 약간 모호합니다. 나는 약간의 설명을 전개 할 것이다.
Benoit

+1하지만 vim많은 일로 나를 이겼지 만 PowerGrep에 충실 할 것이라고 생각합니다.
Lieven Keersmaekers 2011 년

귀하의 답변과 모든 명령에 대한 설명에 감사드립니다. 정말 감사합니다. 나는 이것을 위해 플러그인을 사용하는 것을 선호하기 때문에 다른 대답을 수락하고 있습니다.
psyho 2011 년

질문을하는 사람의 수준과이 답변을 이해하는 데 필요한 수준 사이의 차이를 고려할 때 더 많은 혼란을 야기하기 때문에 이것을 표시했습니다.
Lloyd Moore

22

:args셸 명령에서 채우기

(일부 운영 체제에서 1 )) :args쉘 명령 을 통해 파일을 제공 할 수 있습니다 .

예를 들어 ack 2가 설치된 경우

:args `ack -l pattern`

ack에게 'pattern'이 포함 된 파일 목록을 반환하도록 요청하고이를 인수 목록에 넣습니다.

또는 일반 ol 'grep을 사용하면 다음과 같습니다.

:args `grep -lr pattern .`  


그런 다음 :argdoOP에 설명 된대로 사용할 수 있습니다 .

:argdo %s/pattern/replacement/gce


:args빠른 수정 목록에서 채우기

또한 현재 빠른 수정 목록에서 arglist를 채우는 간단한 사용자 정의 명령을 설명하는 관련 질문에 대한 nelstrom의 대답 을 확인 하십시오. 이는 출력이 퀵 픽스 목록 ( :vimgrep, :Ack3 , :Ggrep4 )에 포함 되는 많은 명령 및 플러그인에서 잘 작동합니다 .

프로젝트 전체 검색을 수행하는 순서는 다음을 사용하여 수행 할 수 있습니다.

:vimgrep /pattern/ **/*
:Qargs 
:argdo %s/findme/replacement/gc

여기서는 :Qargs빠른 수정 목록에서 arglist를 채우는 사용자 정의 명령에 대한 호출입니다.

이 워크 플로우를 2 개 또는 3 개의 명령으로 낮추는 간단한 플러그인 에 대한 후속 토론 에서도 링크를 찾을 수 있습니다 .

연결

  1. : h {arglist} -vimdoc.sourceforge.net/htmldoc/editing.html# {arglist }
  2. ACK - betterthangrep.com/
  3. ack.vim - github.com/mileszs/ack.vim
  4. 도망자 - github.com/tpope/vim-fugitive

1
argdo는 쓰기 문제와 첫 번째 파일 후 중지
frankster


5

외부 의존성을 도입하는 것에 신경 쓰지 않는다면 작업을 수행하기 위해 플러그인 ctrlsf.vim ( ack 또는 ag 에 따라 다름)을 만들었 습니다.

ack / ag의 검색 결과를 포맷하고 표시 할 수 있으며 결과 버퍼의 변경 사항을 디스크의 실제 파일과 동기화 할 수 있습니다.

아마도 다음 데모가 더 많은 것을 설명합니다.

ctrlsf_edit_demo


3
1. :grep <search term> (or whatever you use to populate the quickfix window)
2. :cfdo %s/<search term>/<replace term>/g | update

1 단계에서는 빠른 수정 목록을 원하는 항목으로 채 웁니다. 이 경우을 통해 변경하려는 검색어와 함께 전파됩니다 grep.

cfdo빠른 수정 목록의 각 파일에서 다음 명령을 실행합니다. :help cfdo자세한 내용을 보려면 입력 하십시오.

s/<search term>/<replace term>/g각 용어를 대체합니다. /g파일의 모든 항목을 교체하는 것을 의미합니다.

| update 교체 할 때마다 파일을 저장합니다.

나는 이 답변 과 그 코멘트를 바탕으로 이것을 모았 지만, 모든 것이 한곳에 있기 때문에 그 자체로 대답 할 가치가 있다고 느꼈습니다.


NeoVim에서 저에게는 위의 2 행에서 약간의 수정이 필요했습니다.이 2. :cfdo %s/<search term>/<replace term>/g | update없으면 %패턴의 첫 번째 발생 만 대체됩니다.
Kareem Ergawy

고마워 카림. %s일반 vim에서도 작동하기 때문에 답변을 업데이트했습니다 .
Kyle Heironimus

0

기본적으로 단일 명령으로 교체하고 더 중요한 것은 vim 자체에서

@Jefromi답변 에 따라 다음 과 같이 .vimrc 파일에 설정 한 키보드 단축키를 만들었습니다.

nmap <leader>r :!grep -r -l  * \| xargs sed -i -e 's///g'

이제 vim에서 leader + r 명령을 실행하면 vim에 명령이로드되어 아래와 같이 편집합니다.

:!grep -r -l <find> <file pattern> | xargs sed -i -e 's/<find>/<replace>/g'

따라서 단일 명령으로 교체하고 더 중요한 것은 vim 자체에서


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