Unix/*Nix계통 팁

정통 VI에디터 사용법

ForceCore 2008. 7. 10. 16:55

vi의 정통 사용법을 배워야 하는 이유

솔라리스의 오리지널 vi를 다룰려면 vi의 정통 사용법을 알아두는 것이 좋다.
그리고 vim이라도, 노트북과 같은 화살표도 없고 특수기능 키도 없는
환경에서 편하게 쓰려면 알아두는 것이 좋다.
또 손에 익혀두면 그냥 키보드라도 손을 자꾸 움직이지 않아도 되어서 편하다 -_-;;

vi의 mode

우선 아무 파일이나 열어보기 바란다. 명령어는
$ vi 편집하고싶은파일명
이다. 이미 내용이 충만한 .bashrc파일 같은 것으로 해보길;;

vi에는 세 가지 모드가 있다.

  1. ex모드
  2. 편집모드
  3. 중립모드(?)

용어는 정확히 기억 안 난다 -_-...

편집 모드에서는 키보드로 입력을 하여 내용을 입력할 수 있다.
메모장은 언제나 편집모드라고 이해하면 편집모드를 이해할 수 있다 -_-
편집모드는 (먹힌다면) insert키를 누르면 된다.
안 먹히면, 중립모드에서 i키를 누르면 된다.
그런데... i키에는 조금 문제가 있다.

For a general discussion of the mechanism used to invoke these script[s]

커서가 s에 있는데 그 뒤에다가 see라고 더 적고 싶어졌다면??
([]는 현재 커서의 위치를 나타내는 것이다.)
i키를 누르면 t와 s사이에 글자가 추가된다.
화살표 키가 먹힌다면 s의 다음으로 이동한 다음 작업을 하면 되겠지만.
화살표 키가 안 되는 환경을 가정하면 쓸 수 없는 방법이다.

s라고 한 번 더 입력하고 치고 싶은 말을 친 다음 끝의 s만 삭제해도 되지만,
s에 키가 있는 상태에서, a키를 누르면 s다음으로 커서가 이동 되면서 insert mode에 들어간다.

중립 모드는 vi가 처음 실행되었을 때, 편집모드에서 esc를 눌렀을 때이다.
이 때 명령어를 입력하면 마치 둠1, 둠2의 치트키 입력때와 마찬가지로, 입력한
명령어가 화면에 보이진 않지만 여러가지 신기한 기능이 발동된다.

ex모드는 중립모드에서 :키를 치면 발동된다.
여기서 내리는 명령어는 눈에 보인다 :D

아래 명령어 설명을 할 때 :로 시작하지 않는 것은 중립모드에서 쓰는 명령어,
:로 시작하는 것은 ex모드에서 쓰는 명령어이다.

vi에서의 여러가지 이동

중립모드에서
j키를 몇 번 눌러보고 k키를 몇 번 눌러보라.
커서가 아래로, 위로 움직일 것이다.
이번에는
h, l키를눌러보라. 왼쪽으로, 오른쪽으로 움직일 것이다.
화살표 키를 쓰지 않고도 커서 이동을 할 수 있는 것이다!
노트북에서 매우 유용함.
익숙해지면 그냥 데스크탑에서도 이 키를 쓰게 된다.
왜냐. 오른 손을 jkl있는 곳에서 화살표 키로 움직이기 귀찮으니까 -_-;

하지만 잘못해서 j가 아니라 J를 입력하면 커서가 있는 다음 줄이 커서가 있는 행의 끝에 append 될 것이다.
이는 join line 명령이기 때문이다. 명령에는 대소문자 구분이 있는 것이다.
앞으로 J와 같이 대문자로 표기하면 쉬프트를 누른 상태에서 j키를 누르는 것을 나타낸다.

j를 계속 누르고 있으면 빨리 내려가긴 하지만 그래도 성질이 급한 사람은 page up, page down을 써야 할 것이다.
하지만 그 키가 없는 키보드나 (-_-) 정통 vi라면?
ctrl+u, ctrl+d를 눌러보자.
각각 up, down역할을 한다.

한편 세로의 이동 뿐 아니라 가로의 이동을 빠르게 하는 기능도 존재한다.
w키를 누르면 한 단어씩 오른쪽으로 건너 뛴다.
b키를 누르면 한 단어씩 왼쪽으로 건너 뛸 것이다.

또 재미있는 기능이 있는데...
코딩을 하다 보면 위에서 아래로 해나가기 때문에...
화면의 절반 정도는 기존에 한 코딩이 보이고 아래 절반은
빈 칸이 보여야지 뭔가 심리적으로 안정적이 되는데...
vim에선 그 작업을 편하게 하기 위한 키가 존재한다.
zz는 현재 커서가 있는 곳을 화면의 정확히 중간에 놓는다.
ctrl+e는 커서를 현재 행에 둔 채로 화면을 위로 스크롤 한다.
ctrl+y는 커서를 현재 행에 둔 채로 화면을 아래 스크롤 한다.

삭제

중립모드에서
dd라고 해보자.
커서가 있는 한 줄이 삭제될 것이다.
:d: 한 줄 삭제. (ex모드라는 차이점이 있음)
dw: delete word. 현재 커서의 위치로부터 그 단어의 끝까지 삭제.
x: delete character. 현재 커서 아래의 한 char를 삭제. del키가 안 먹히는 환경에서 유리.
D: 현재 커서가 있는 곳 부터 끝까지 삭제. 윈도우 메모장으로 치자면, 쉬프트+엔드 선택뒤 딜리트를 누르는 콤보.

다시, 여러가지 이동

:d로 ex mode를 본 김에 한 가지 해보자.
:숫자
goto line 기능이다. :10이라고 하면 10번째 줄로 커서가 이동할 것이다.
코딩을 하다가 몇 행에서 에러가 났다고 컴파일러가 알려주면
그 행으로 갈 때 쓸모 있다.

코딩 이야기가 나와서 말인데,
나중에 Makefile이란 것을 쓰게 될 수도 있다 -_-;;
:make를 하면 vim에서 make를 invoke 해준다. 그다지 쓸모 있게 써본 적은 없음.
필자는 주로 screen으로 다중 작업을 하는 편이기 때문이다.

goto line이외 순간이동:

gg: 파일의 첫 머리로 이동(vim이면 되고, 정통 vi면 안 된다. 이 경우 :1를 이용하면 된다).
GG: 파일의 끝으로 이동.
0: home키에 해당. 윈도우 메모장의... O(오) 가 아니고 0(제로)이다.
^: visual studio의 home키에 해당?;; indenting이 된 line의 경우 첫 번째의 공백 아닌 character로 이동한다.
$: 윈도우 메모장의 end키에 해당.

Repeat 기능

그런데 dd로 여러 줄을 삭제하려면 귀찮을 것이다.
dd를 계속 누르면 되지만 d키를 두 번 눌러야 겨우 한 줄 삭제되는 꼴이다.
이런 때에는 dd를 눌러서 한 줄만 삭제한 뒤
.키를 눌러보자. .(점)은 repeat기능이다.
마지막으로 한 작업이 repeat 되는 것이다.

곱하기 기능

그래도 100줄 지우려면 .도 귀찮다.
100dd라고 하면 100줄이 삭제된다.
혹은 :100d
vi의 특성인데, 명령어를 치기 전에 숫자를 치면 그만큼 "반복"적으로 명령어가 적용되는 것이다.
역시 마찬가지로 10x라고 하면 10 character가 삭제된다. 오옷!

Undo 기능

이제쯤에선 삭제를 남발한 탓에 파일의 내용이 많이 없어졌을 것이다 -_-;;
.이 repeat였다면 u는 undo이다.
undo를 몇 번 해보자. 몇 step까지 undo되는진 기억 안 나지만...

Redo는 컨트롤 R이다.

ex mode에서의 저장과 종료

그런데 undo로 살리는 것도 한계가 있다.
여러번 undo하기도 귀찮고.
마지막으로 저장된 상태로 revert 해보자.
뽀샵으로 치자면 File -> Revert to Saved File 정도 된다.
:e!
원래 :e는 open file 명령어라서 :e 파일명 이라고 입력하면 파일을 열게 되는 것임.

종료를 할 때는
:q
이다.

편집을 해놓고 저장을 하지 않았다면 저장하지 않았다고 경고가 뜨고 종료는 안 될 것이다.
저장을 할 때에는
:w
이다.

하지만 :w를 한 뒤 :q를 하려면 귀찮잖아.
저장을 하면서 종료할 때에는
:wq
를 쓴다.

root로 작업하는데 root로도 read 권한만이 있는 파일을 건드리는 경우가 더러 있을 것이다.
그러면 :wq가 안 먹히는데... 종료해서 편집 내용을 날려먹은 뒤
chmod +w 했다가 다시 처음부터 편집하고, chmod -w를 쓰는 등
쓸 수 있게 만들었다가 다시 읽기 전용으로 만들긴 귀찮을 것이다.
그런 때는 :wq!를 쓰면 된다. 강제로 write 권한을 주었다가 write하고 다시 읽기 전용으로 만들어준다.

그런데 편집한 것이 마음에 안 들어서 저장하지 않고 종료하고 싶은 때가 있을 것이다.
:e!를 한 다음 :q를 하면 되는데 이것도 귀찮잖아.
:q!
만 하면 저장하지 않고 종료하는 것이다.

복사와 붙여넣기

다시 아까의 dd로 돌아와보자.
한 줄만 dd라고 해보고,
다른 곳으로 이동해서 p를 눌러보라.
dd로 삭제된 것은 파일에서는 삭제 되었지만, 메모리에 복사가 된다.
말 하자면 cut and paste인 것이다.

이는 다른 delete기능도 마찬가지여서 x나 dw도 똑같이 삭제된 내용을
p로 다른 곳에 붙여넣기 할 수 있다.

하지만 cut말고 copy and paste를 하고 싶은 경우에는?
dd대신 yy를 누른다.
그러면 그 줄이 복사된다.

아까 곱하기 기능에 대해서 이야기 했었다.
100dd 라고 했으면 p를 눌렀을 때 그 삭제된 100줄 모두가 paste되고
100yy라고 하면 100줄이 복사되어서 나중에 p를 누르면 붙여진다.
yy대신 :y, :100y 이런 식으로 해도 된다.

한편 또 다른 문제가 있다.
파일의 제일 처음에 붙여넣기를 하고 싶어졌을 수도 있다.
p키 만으론 현재의 line1 이전에 뭔가를 붙여넣으려면 p로 붙여넣기를 한 다음에
원래의 첫 줄을 dd시킨 다음 다시 붙여 넣어서 순서를 바꿔야 한다.
하지만 그 점 역시 고려되어 있다.
P키를 누르면 현재의 커서 이전에 붙여넣기가 될 것이다.

검색과 교체

이제 복사 붙여넣기, 이동, 삭제는 거의 다 했다.
아직 못 한 것이 있으니 search/replace이다.

search를 하려면 /를 누른다.
:를 눌렀을 때와 비슷하게 아래에 /가 뜬다.
이제 검색어를 입력하고 엔터.

사실 vi의 검색은 정규표현식 검색이라서
[]와 같은 특수문자는 이상하게 검색될 수도 있는데
\[\]와 같이 \를 붙이면 해결된다.

검색에는 대소문자 구분이 있다.
물론 개인 설정을 이용하면 case insensitive search도 되지만 그건 알아서
구글에 vim case insensitive search라고 물어보자 -_-;

이 쯤에서 cw에 대해 설명해야 겠다.
qwertyuiop
라는 단어가 있으면
qw[e]rtyuiop처럼 e에다가 커서가 오게 하자.
cw라고 누르면
qw[e]rtyuio$
이렇게 보이거나, vim이라면
qw가 될 것이다.
어느 경우를 했든, 현재 자동빵으로 편집모드로 들어온 것이다.
즉, e부터 그 단어의 끝까지 다른 말로 change word되는 것이다.
qw로 보이는 경우 쓸 말을 평소 하던 대로 덧붙여서 쓰면 된다.
qw[e]rtyuio$이렇게 보이는 경우도 그냥 아무 말이나 치기 시작하면 $까지 보이던 것이 없어지면서
원하는 단어로 잘 적힐 것이다.

근데
/etc/apache2같은 게 있으면
/etc를 바꾸려고 하는데 /에 커서를 놓고 cw를 누르면 /만 교체되려고 할 것이다 -_-;;
이런 경우에는 사람이 몇 글자를 바꾸고 싶은지 세어야 한다.
4cl로 네 번의 change letter를 하고 싶은지 정해주면 위와 마찬가지로 된다.

이제 기본기가 되었으니 replace를 해볼까?
문서 내의 the를 모두 The로 바꿔보자.
/the
엔터.
the가 하나 검색된다.
cw를 누른뒤 The라고 입력, esc키를 눌러 중립모드로 돌아온다.

N
은 윈도우 메모장으로 치자면, 한 번의 search가 이미 이루어진 뒤에
F3키를 눌러서 똑같은 것을 또 검색하는 작업이다.
한편 N은 search방향을 아래에서 위로 한다.

n키를 눌러서 다음 the를 찾는다.
아까 cw작업을 했기 때문에 이번에는 .만 눌러도 the가 The로 바뀔 것이다 +_+
글자를 바꾸는데 dw하여 삭제한 뒤 insert를 하지 않는 이유가 이 repeat 기능 때문이다.
dw하고 insert를 하면 .을 눌렀을 때 삭제는 안 되고 insert만 될 것이다.

Indenting

이제 사소한 것 몇 개만 남았다.
코딩을 할 때,

int main() {
  int a;
  a = 0;
  ++a;
  return 0;
}

이런 코드 있다고 하자.
만약 없던 if문이 새로 생겼다면... 여러 줄을 indenting 하고 싶어질 것이다.

int main() {
  if( b == 0 ) {
  int a;
  a = 0;
  ++a;
  }
  return 0;
}

우선은 이렇게 if와 괄호만 새로 적었다고 치자.
int a; 부터 ++a; 세 줄을 indenting해보자.

int a;가 있는 행에 커서를 이동시킨다.
>>를 누르면 그 줄이 오른쪽으로 indenting 될 것이다.
<<를 누르면 그 줄이 왼쪽으로 indenting된다.
이제 곱하기 기능을 이용하여 3>>라고 하면

int main() {
   if( b == 0 ) {
    int a;
    a = 0;
    ++a;
  }
  return 0;
}

이렇게 된다. Repeat 기능을 사용해도 좋다.

Visual Block

이제부터 vim에만 되는 설명...
dd나, <<나 >>나, yy나...
이런건 행이 몇 행인지 세어야지 여러 줄에 적용할 수 있다.
몇 줄 안 되면 세기도 쉬워서 굳이 여기서 가르쳐주는 기능을 안 써도 되는데,
한 14줄 이런 눈으로 세기 애매한 숫자면 좀 낭패.

중립모드에서 v라고 쳐보자.
이는 제 4의 모드인 visual block mode이다.
v를 누른 뒤 hjkl이나, 된다면 화살표 키를 써서 삭제/복사/indenting하고 싶은 영역을 선택한다.
윈도우용 vim에서는 화살표 키를 치는 순간 visual block mode가 풀려서 hjkl키를 써야만 함 -_-;;
선택 되었으면 >>나 dd나 쓰고 싶은 것을 맘대로 쓰면 된다.

visual block mode에서 쓸 수 있는 유용한 키가 또 있는데...
바로 자동 indenting이다.

int main() {
if( b == 0 ) {
int a;
a = 0;
++a;
}
return 0;
}

이런 indenting이 되지 않은 지저분한 소스코드를 block 지정한 다음 ,
=키를 누르면 block으로 선택된 부분이 자동 indenting이 된다.

사실 = 키는 쓰기 어려운 기능이다.
19=30 처럼 시작범위, 끝 범위를 알고 있어야 된다.

하지만 전체 indenting의 경우
gg=G
라고 하면 끝.

참고 자료

이 정도를 알면 vi를 편하게 쓰는데 지장이 전혀 없다.
하지만 이 문서에서 커버하고 있는 기능은 많다고 할 수 없다.
자잘한 기능까지 다 알고 싶으면
http://www.unix.com.ua/orelly/unix/vi/index.htm
를 참고하기 바란다. 정통 vi에디터와 vim을 모두 다루고 있다.