Vim 의 문제점 은 vi 를 좋아하지 않는다는 것 입니다.
절단을 언급 yy
하고 거의 모든 라인을 절단하고 싶지 않다고 불평합니다. 실제로 프로그래머, 소스 코드 편집은 종종 전체 라인, 라인 범위 및 코드 블록에서 작업하기를 원합니다. 그러나 yy
텍스트를 익명의 복사 버퍼 (또는 vi 에서 호출 된 "register")에 넣을 수있는 여러 방법 중 하나 일뿐 입니다.
vi 의 "젠"은 당신이 언어를 말하는 것입니다. 이니셜 y
은 동사입니다. 이 문장 yy
은의 동의어입니다 y_
. 은 y
이 같은 일반적인 작업이기 때문에 쉽게 입력 할 수 있도록 두 배로됩니다.
dd
P
(현재 행을 삭제하고 사본을 다시 붙여넣고 익명 레지스터에 사본을 부작용으로 남겨 두십시오) 로 표현할 수도 있습니다 . y
및 d
"동사"그 같은 움직임을 "될 수 있습니다." 따라서 yW
"여기 (커서)에서 현재 / 다음 (큰) 단어의 끝까지"이고 y'a
"여기에서 ' a ' 라는 마크를 포함하는 행까지 입니다."
기본 위, 아래, 왼쪽 및 오른쪽 커서 이동 만 이해하면 vi 는 "메모장"복사본보다 더 생산적이지 않습니다. (좋아요, 여전히 구문 강조 표시와 ~ 45KB 정도의 파일보다 큰 파일을 처리하는 기능이 있지만 여기에서 나와 함께 작업하십시오).
vi 에는 26 개의 "마크"및 26 개의 "레지스터"가 있습니다. m
명령을 사용하여 마크가 커서 위치로 설정됩니다 . 각 마크는 하나의 소문자로 지정됩니다. 따라서 ma
' a '마크를 현재 위치로 mz
설정하고 ' z '마크를 설정합니다 . '
(작은 따옴표) 명령을 사용하여 마크가 포함 된 줄로 이동할 수 있습니다 . 따라서 'a
' a '표시 가있는 줄의 시작 부분으로 이동합니다 . `
(backquote) 명령을 사용하여 마크의 정확한 위치로 이동할 수 있습니다 . 따라서 `z
' z '표시 의 정확한 위치로 직접 이동 합니다.
이들은 "움직임"이기 때문에 다른 "문"의 주제로 사용될 수도 있습니다.
따라서 임의의 텍스트 선택을 잘라내는 한 가지 방법은 마크를 삭제하는 것입니다 (보통 ' a '를 "첫 번째"마크로, ' z '를 다음 마크로, ' b '를 다른 마크로, ' e '를 또 다른 것 ( vi 를 사용한지 15 년 만에 4 개 이상의 마크를 인터랙티브하게 사용한 적이 있다는 것을 기억하지 못합니다 . 하나는 대화 형 컨텍스트를 방해하지 않는 매크로가 마크와 레지스터를 사용하는 방법에 대한 고유 한 규칙을 만듭니다). 원하는 텍스트의 다른 쪽 끝으로; 우리는 어느쪽에서든 시작해도 상관 없습니다. 단순히 d`a
잘라내거나 y`a
복사 하는 데 사용할 수 있습니다 . 따라서 전체 프로세스에는 5 번의 키 입력 오버 헤드가 있습니다 ( "삽입에서 시작하면 6 번 "모드와 필요한Esc아웃 명령 모드). 잘라내거나 복사 한 후 사본에 붙여 넣는 것은 한 번의 키 입력 p
입니다.
나는 이것이 텍스트를 자르거나 복사하는 한 가지 방법이라고 말합니다. 그러나 그것은 많은 것 중 하나 일뿐입니다. 종종 커서를 움직이거나 마크를 떨어 뜨리지 않고 텍스트 범위를 더 간결하게 설명 할 수 있습니다. 예를 들어 내가 사용할 수있는 텍스트의 단락에있어 경우 {
와 }
각각 단락의 처음이나 끝으로 이동. 따라서 텍스트 단락을 이동하려면 {
d}
(3 키 누름)을 사용하여 잘라 냅니다. (문단의 첫 번째 또는 마지막 줄에 이미있는 경우 간단히 d}
또는 d{
각각을 사용할 수 있습니다 .
"문단"의 개념은 일반적으로 직관적으로 합리적인 것으로 기본 설정됩니다. 따라서 종종 코드뿐만 아니라 산문에서도 작동합니다.
우리는 종종 관심있는 텍스트의 한쪽 끝을 나타내는 패턴 (정규 표현식)을 알고 있습니다. 앞으로 또는 뒤로 검색은 vi 에서 이동 합니다. 따라서 그것들은 또한 우리의 "명명 서"에서 "대상"으로 사용될 수 있습니다. 따라서 d/foo
현재 줄에서 문자열 "foo"를 포함하는 다음 줄로 잘라 내고 현재 줄에서 y?bar
"bar"를 포함하는 가장 최근 (이전) 줄로 복사하는 데 사용할 수 있습니다. 전체 줄을 원하지 않으면 여전히 검색 동작을 사용할 수 있습니다 (자신의 진술로). 내 마크를 삭제하고 `x
앞에서 설명한 명령을 사용하십시오 .
"동사"와 "대상" 이외에도 vi 에는 "개체"(용어의 문법적 의미)가 있습니다. 지금까지는 익명 레지스터 사용에 대해서만 설명했습니다. 그러나 "object"참조 접두사"
(큰 따옴표 수정 자)로 26 개의 "명명 된"레지스터 중 하나를 사용할 수 있습니다 . 따라서 내가 사용 "add
하면 현재 줄을 ' a '레지스터 로 자르고 사용 "by/foo
하면 텍스트의 사본을 여기에서 ' b '레지스터에 "foo"를 포함하는 다음 줄로 가져갑니다 . 레지스터에서 붙여 넣기하려면 붙여 넣기에 동일한 수정 자 시퀀스를 붙여 넣기 만하면됩니다. "ap
' a '레지스터 ' 의 복사본을 붙여 넣기"bP
' b '에서 현재 행 앞에 사본을 붙여 넣습니다 .
"접두사"라는 개념은 문법 조작법 "형용사"와 "부사"를 텍스트 조작 "언어"에 추가합니다. 대부분의 명령 (동사)과 움직임 (상황에 따라 동사 나 사물)도 숫자 접두사를 사용할 수 있습니다. 3J
"다음 세 줄에 합류"를 d5}
의미하고 "여기에서 다섯 번째 단락 끝까지 현재 줄에서 삭제 "를 의미합니다.
이것은 모든 중간 레벨 vi 입니다. Vim 에만 해당되는 것은 없으며 vi 를 배울 준비가 되었다면 vi 에는 훨씬 더 고급 트릭 이 있습니다. 이러한 중간 개념을 숙달했다면 텍스트 조작 언어가 편집기의 "네이티브"언어를 사용하여 대부분의 작업을 쉽게 수행 할 수있을만큼 간결하고 표현 적이기 때문에 매크로를 작성할 필요가 거의 없을 것입니다.
더 고급 트릭의 샘플링 :
많은 :
명령, 특히 :% s/foo/bar/g
전역 대체 기술이 있습니다. (고급 기능은 아니지만 다른 :
명령도 가능합니다). vi 의 이전 화신에 :
의해 전체 명령 세트는 역사적 으로 ed (라인 편집기) 및 나중에 ex (확장 라인 편집기) 유틸리티로 상속되었습니다 . 사실 vi 는 ex 의 시각적 인터페이스이기 때문에 그렇게 명명되었습니다 .
:
명령은 일반적으로 텍스트 줄에서 작동합니다. ed 와 ex 는 터미널 화면이 흔하지 않았고 많은 터미널이 "TTY (teletype)"장치였던 시대에 쓰여졌습니다. 따라서 매우 간결한 인터페이스를 통해 명령을 사용하여 인쇄 된 텍스트 사본으로 작업하는 것이 일반적이었습니다 (일반적인 연결 속도는 110 보드 또는 대략 11 자 (초당 11 자)). 빠른 타이피스트보다 느립니다. 다중 사용자 대화식 세션; 또한 종이를 절약하려는 동기가 종종있었습니다).
따라서 대부분의 :
명령 구문 에는 주소 또는 주소 범위 (행 번호)와 명령이 포함됩니다. 자연스럽게 리터럴 행 번호를 사용할 수있다 : :127,215 s/foo/bar
또한 일부 약어를 사용할 수있는 하나의 127 내지 215 각각의 행에 "바"로 "foo는"처음 발견을 변경 .
하거나 $
각각 현재 및 마지막 라인. 하나는 상대 접두사를 사용할 수 +
와 -
각각 후 또는 curent 라인 전에 오프셋 (offset)를 참조하십시오. 따라서 :.,$j
"현재 줄에서 마지막 줄까지 모두 한 줄로 연결"을 의미합니다. (모든 줄) :%
과 동의어입니다 :1,$
.
:... g
과 :... v
그들이 믿을 수 없을만큼 강력한으로 명령은 몇 가지 설명을 부담. :... g
는 패턴 (정규 표현식)과 일치하는 모든 행에 후속 명령을 적용하는 "전역 적으로"접두어이며 :... v
, 지정된 패턴 ( "conVerse"의 "v")과 일치하지 않는 모든 행에 이러한 명령을 적용합니다. 다른 ex 명령과 마찬가지로 주소 / 범위 참조로 접두사를 붙일 수 있습니다. 따라서 :.,+21g/foo/d
"현재 줄에서 다음 21 줄까지"foo "문자열을 포함하는 모든 줄을 삭제함"을 :.,$v/bar/d
의미하고 "여기에서 파일 끝까지 문자열"bar "를 포함하지 않는 모든 줄을 삭제하십시오.
일반적인 Unix 명령 grep 이 실제로이 ex 명령에서 영감을 얻은 것입니다 (그리고 문서화 된 방식에 따라 이름이 지정됨). 전직 명령 :g/re/p
(GREP은)가 "세계", "정규 표현식"(재) "는이 포함 된 라인"을 인쇄하는 방법을 설명 된 방법이었다. 시 에드 와 전이 사용되었다의 :p
명령은 사람이 배운 모든 파일을 편집 할 때 종종 처음 사용하는 최초의 하나였다. 그것은 당신이 현재 내용을 인쇄하는 방법이었습니다 (보통 한 번에 한 페이지 씩 가득 채 :.,+25p
웁니다).
참고 :% g/.../d
하거나 (그 역 / CONVERSE 대응 : :% v/.../d
가장 일반적인 사용 패턴이다 그러나 다른 몇 가지가 있습니다. ex
가치가 기억하는있는 명령 :
우리는 m
라인을 이동하고 라인 j
을 결합 하는데 사용할 수 있습니다 . 예를 들어 목록이 있고 모든 물건 일치 (또는 일부 패턴과 일치하지 않는)를 삭제하지 않고 분리하고 싶다면 다음과 같이 사용할 수 있습니다 : :% g/foo/m$
... 모든 "foo"줄이 파일의 끝. 파일 끝을 스크래치 공간으로 사용하는 방법에 대한 다른 팁을 참고하십시오. 이것은 모든 "foo"라인의 상대적 순서를 유지하면서리스트의 나머지 부분에서 추출합니다. (이것은 다음과 같은 작업과 같습니다. 1G!GGmap!Ggrep foo<ENTER>1G:1,'a g/foo'/d
(파일을 자체 꼬리에 복사하고 꼬리를 필터링 grep
하여 머리에서 모든 것을 삭제하십시오).
일반적으로 선을 결합하려면 선행 작업에 결합해야하는 모든 선 (예 : 일부 글 머리 기호 목록에서 "^ *"가 아닌 "^"로 시작하는 모든 선)에 대한 패턴을 찾을 수 있습니다. 이 경우에는 다음을 사용합니다. :% g/^ /-1j
(일치하는 모든 줄마다 한 줄 위로 올라가서 합류하십시오). (BTW : 글 머리 기호 목록을 ... 또 다른 하나 개의 총알 라인을 몇 가지 이유로하지 작업에 가입 할 수 있습니다 않는 총알 라인을 검색하고 다음에 가입을 시도하고 것이 어떤 총알 라인에 가입하지 않습니다 모두 의 그 연속; 경기에서만 쌍으로 작동합니다).
거의 말할 것도없이 옛 친구 s
(대체)를 g
and v
(global / converse-global) 명령 과 함께 사용할 수 있습니다 . 일반적으로 그렇게 할 필요는 없습니다. 그러나 다른 패턴과 일치하는 행에서만 대체를 수행하려는 경우를 고려하십시오. 종종 캡처와 함께 복잡한 패턴을 사용하고 변경하지 않으려는 라인 부분을 보존하기 위해 역 참조를 사용할 수 있습니다. 그러나, :% g/foo/s/bar/zzz/g
"foo"를 포함하는 모든 줄에 대해 "zzz"로 모든 "bar"를 대체하십시오. (같은 것:% s/\(.*foo.*\)bar\(.*\)/\1zzz\2/g
같은 줄에서 "foo"에 의해 선행 된 "bar"인스턴스의 경우에만 작동합니다. 이미 충분하지 않으며 "bar"가 "foo"앞에있는 모든 경우를 잡으려면 더 엉망이되어야합니다.)
요점은보다 더 있다는 것입니다 p
, s
그리고 d
에서 선 ex
명령 세트를.
:
주소는 표시를 참조 할 수 있습니다. 따라서 :'a,'bg/foo/j
' a '와 ' b '표시 사이의 행 사이에 있으면 문자열 foo를 포함하는 모든 행을 후속 행에 결합 할 수 있습니다 . (예, 위의 모든 ex
명령 예제는 이러한 종류의 주소 지정 표현식을 접두어로 사용하여 파일 행의 서브 세트로 제한 될 수 있습니다).
그것은 꽤 모호합니다 (지난 15 년 동안 몇 번만 그런 것을 사용했습니다). 그러나 올바른 수정을 생각하기 위해 시간을 내면 더 효율적으로 수행되었을 수있는 반복적이고 대화식으로 자주 작업을 수행했음을 자유롭게 인정할 것입니다.
또 다른 매우 유용한 vi 또는 ex 명령은 :r
다른 파일의 내용을 읽는 것입니다. 따라서 : :r foo
"foo"라는 파일의 내용을 현재 행에 삽입합니다.
:r!
명령 이 더 강력합니다 . 명령 결과를 읽습니다. vi 세션 일시 중단, 명령 실행, 출력을 임시 파일로 경로 재 지정, vi 세션 재개 및 임시 컨텐츠를 읽는 것과 동일합니다. 파일.
!
(bang) 및 :... !
( ex bang) 명령 이 더 강력 합니다. 또한 외부 명령을 실행하고 결과를 현재 텍스트로 읽습니다. 그러나 명령을 통해 텍스트 선택을 필터링합니다! 이것은 우리가 사용하는 우리의 파일의 모든 라인을 정렬 할 수 있습니다 1G!Gsort
( G
는 IS VI , 파일의 마지막 줄에 가기가 기본값 있지만, 이러한 일, 첫 번째 줄, 줄 번호 접두어 할 수있다 "고토"명령). 이것은 ex 변형 과 동일합니다 :1,$!sort
. 작가는 종종 텍스트 선택을 재구성하거나 "단어 줄 바꿈"하기 위해 !
Unix fmt 또는 fold 유틸리티 와 함께 사용 합니다. 매우 일반적인 매크로는{!}fmt
(현재 단락을 다시 포맷하십시오). 프로그래머는 때때로 들여 쓰기 또는 다른 코드 재 형식화 도구를 통해 코드를 실행하거나 코드의 일부만 실행하기 위해이 코드를 사용합니다.
:r!
and !
명령을 사용하면 외부 유틸리티 나 필터를 편집기의 확장으로 취급 할 수 있습니다. 데이터베이스에서 데이터를 가져 오는 스크립트 나 웹 사이트에서 데이터를 가져 오는 wget 또는 lynx 명령 또는 원격 시스템에서 데이터를 가져 오는 ssh 명령과 함께 사용했습니다.
또 다른 유용한 ex 명령은 :so
(약칭 :source
)입니다. 파일 내용을 일련의 명령으로 읽습니다. vi 를 정상적으로 시작하면 암시 적으로 :source
on ~/.exinitrc
파일을 수행 합니다 ( Vim은 보통 ~/.vimrc
자연스럽게 충분합니다). 이를 사용하면 새로운 매크로, 약어 및 편집기 설정을 소싱하여 편집기 프로파일을 즉석에서 변경할 수 있습니다. 비열한 사람이라면 필요 에 따라 파일에 적용하기 위해 일련의 ex 편집 명령을 저장하는 트릭으로 사용할 수도 있습니다 .
예를 들어 wc 통해 파일을 실행하는 7 줄 파일 (36 자)이 있고 해당 단어 수 데이터가 포함 된 파일 맨 위에 C 스타일 주석을 삽입합니다. 다음과 같은 명령을 사용하여 해당 "매크로"를 파일에 적용 할 수 있습니다.vim +'so mymacro.ex' ./mytarget
( vi 와 Vim에 대한 +
명령 행 옵션 은 일반적으로 주어진 행 번호에서 편집 세션을 시작하는 데 사용됩니다. 그러나 "source"명령과 같은 유효한 ex 명령 / 표현식을 사용할 수 있다는 것은 알려진 사실이 아닙니다. 간단한 예제를 위해 다음 과 같이 호출하는 스크립트 가 있습니다. 서버 세트를 다시 이미징하는 동안 SSH 알려진 호스트 파일에서 비 대화식으로 항목을 제거합니다.+
vi +'/foo/d|wq!' ~/.ssh/known_hosts
일반적으로 Perl, AWK, sed를 사용하여 이러한 "매크로"를 작성하는 것이 훨씬 쉽습니다 (실제로 ed 명령에서 영감을 얻은 유틸리티 grep 과 같습니다 ).
이 @
명령은 아마도 가장 모호한 vi 명령 일 것입니다. 때때로 10 년 가까이에 고급 시스템 관리 과정을 가르 칠 때 나는 그것을 사용해 본 사람이 거의 없었습니다. @
레지스터 내용을 마치 vi 또는 ex 명령 인 것처럼 실행합니다 .
예 : 나는 종종 :r!locate ...
시스템에서 파일을 찾아 내 이름을 문서로 읽는 데 사용합니다. 거기에서 불필요한 히트를 삭제하고 관심있는 파일의 전체 경로 만 남겨 둡니다. Tab경로의 각 구성 요소를 힘들게 사용하지 않고 (또는 탭 완성 지원이없는 컴퓨터에 붙어있는 경우 더 나빠집니다) vi 의 사본에서 ) 나는 다음을 사용합니다.
0i:r
(현재 줄을 유효한 : r 명령 으로 바꾸려면 )
"cdd
( "c"레지스터의 행을 삭제하기 위해)
@c
해당 명령을 실행하십시오.
그것은 10 "cdd
@c
번의 키 입력입니다 (그리고 표현 은 사실상 손가락 매크로입니다. 그래서 일반적인 6 글자만큼 빨리 입력 할 수 있습니다).
냉정한 생각
나는 vi 의 힘의 표면에 흠집을 냈으며 여기에서 설명 한 것은 vim 이라는 이름 의 "개선"의 일부조차 아닙니다 ! 여기에 설명 된 모든 내용 은 20 년 또는 30 년 전에 vi의 오래된 사본에서 작동해야합니다 .
내가 할 것보다 vi 의 힘을 훨씬 더 많이 사용한 사람들이 있습니다 .