目錄表

圖解鍵盤指令

http://blog.vgod.tw/2009/12/08/vim-cheat-sheet-for-programmers/

http://www.viemu.com/a_vi_vim_graphical_cheat_sheet_tutorial.html

Text Entry Mode

進去 vim 最開始的狀態(按 Esc 可從其他狀態跳過來)

Key Action
i 在游標前面插入文字
I 在行首插入文字
a 在游標後面插入文字
A 在行尾插入文字
o 在游標下一行插入文字
O 在游標前一行插入文字
r 取代一個字元
R 進入取代模式
J 將下一行合併到此行結尾
V 選取模式(反白)
!<command> 執行 shell 指令
Key Movement
k
j
l
h
︿ 行首
$ 行尾
b 往前一個單字
w 往後一個單字
e 前一個單字的尾端
H 螢幕頂端
M 螢幕中間
L 螢幕底端
Ctrl+d 下移半個螢幕
Ctrl+u 上移半個螢幕
Ctrl+f 下移一個螢幕
Ctrl+b 上移一個螢幕
:nn 跳到第 nn 行
gg 跳到檔案開頭
G 跳到檔案結尾
Key Delete
x 刪除一個字元
dw 刪除一個單字
dd 刪除一整行
:<range>d 刪除範圍(Command mode)
Key Replace
cw 刪除一個單字,並進入插入模式
cc 刪除一整行,並進入插入模式
Key Copy
:<range>y複製範圍
Y 複製此行
p 在下一行貼上
:nnpu 在第nn行後貼上

套裝鍵

gg=G 程式碼重新縮排
ggVGy 全選+複製

Command Mode

先輸入一個冒號(:)即可進入指令模式

動作範圍

: 1 , 3 d     #刪除第一到三行
: . , . +2 d    # 刪除游標所在行到後兩行(共三行)
Range Selects
.(句點) 游標所在行
$ 檔案的最後一行
1 , $ 第一行到最後一行
1 , . 第一行到游標所在行
. , $ 游標所在行到最後一行
. -2 游標所在行的兩行前(5 → 3)
Key1) Search and replace
:<range>s/aaa/bbb/ 將範圍內每行開頭出現的 aaa 字串替換成 bbb
:<range>s/aaa/bbb/g 將範圍內所有 aaa 字串替換成 bbb
:%s/aaa/bbb/ 將整個文件所有 aaa 字串替換成 bbb
: % s/︿v︿m/ /g 將 dos 格式的文章轉成 Linux 格式,先按 Ctrl+v 然後按 Ctrl+m
Key Save/Load
:<range> w <name> 將範圍內資料另存新檔
:r <name> 插入指定檔案的內容
:n 下個檔案

Insert Mode

自動補齊

http://www.openfoundry.org/index.php?option=com_content&task=view&id=2215&Itemid=334

C-x C-l 行補齊
C-x C-n 以目前檔案做關鍵字補齊

tabs

一次用 tab 打開很多檔案

$ vim -p file1 file2 file3 ...
Command Action
:tabnew [filename] 開新分頁[指定分頁名稱 filename]
:tabf filename 用 tab 打開現在所在目錄下的檔案filename
:tabm [num] 將目前的 tab 移到指定數字位置(0為最前面,若沒輸入 num,則移到最後面)
:tabn 切換到下一個分頁
:tabp 切換到前一個分頁
:tabs 顯示所有分頁資訊
:tabfir 跳到第一個分頁
:tablast 跳到最後一個分頁
:tabdo [指令] 對所有 tabs 執行指令2)

說明文件

:help tab-page-intro

畫面切割

:sp filename 橫向切割
:vsp filename 是縱向切割
Ctrl+w Ctrl+w 切換到另一個視窗

環境設定

支援 UTF8

:set enc=utf8
:set fileencoding=utf8 

Mapping

參考:Using Vim mappings and abbreviations

程式碼轉成 HTML

命令模式下輸入

:so \$VIMRUNTIME/syntax/2html.vim

可將螢幕上高亮度顯示的文字轉化為HTML 文字, 然後用 :w file.html 存檔, :q 退出

另一種,會出現分割視窗。

:TOhtml

清除 html tag

%s/<\_[^>]*>//g

在文件前加上行號

:%s/^.*$/\=line(”.”) . ” ” . submatch(0)/g

將網頁字碼轉成中文字

:set enc=utf8
:%s/&#\([0-9]\+\);/\=nr2char(submatch(1))/g

Plugins

Vundle

https://github.com/VundleVim/Vundle.vim

管理外掛的工具

vimagit

https://github.com/jreybert/vimagit

和 git 結合方便操作 git

snipMate

http://www.vim.org/scripts/script.php?script_id=2540

類色 TextMate 的自動完成功能。

javacomplete

Omni Completion for JAVA

http://www.vim.org/scripts/script.php?script_id=1785

taglist

Source code browser (supports C/C++, java, perl, python, tcl, sql, php, etc)

http://www.vim.org/scripts/script.php?script_id=273

cppcomplete

C/C++ and Java code completion

http://www.vim.org/scripts/script.php?script_id=527

cTag

http://adrianhuang.blogspot.com/2007/09/trace-code-gvimctagscscope.html

http://ctags.sourceforge.net/

nerd tree

http://www.catonmat.net/blog/vim-plugins-nerdtree-vim/

Allows you to explore the file system and open files and directories directly from vim.

Reference

Vim Cookbook:http://www.oualline.com/vim-cook.html

COSCUP 2009 by c9s:http://www.slideshare.net/c9s/vim-hacks

Vim Hacks (OSSF) by c9s:http://www.slideshare.net/c9s/vim-hacks-ossf

vimrc

http://amix.dk/vim/vimrc.html

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Maintainer: amix the lucky stiff
"             http://amix.dk - amix@amix.dk
"
" Version: 3.3 - 21/01/10 01:05:46
"
" Blog_post: 
"       http://amix.dk/blog/post/19486#The-ultimate-vim-configuration-vimrc
" Syntax_highlighted:
"       http://amix.dk/vim/vimrc.html
" Raw_version: 
"       http://amix.dk/vim/vimrc.txt
"
" How_to_Install:
"    $ mkdir ~/.vim_runtime
"    $ svn co svn://orangoo.com/vim ~/.vim_runtime
"    $ cat ~/.vim_runtime/install.sh
"    $ sh ~/.vim_runtime/install.sh <system>
"      <sytem> can be `mac`, `linux` or `windows`
"
" How_to_Upgrade:
"    $ svn update ~/.vim_runtime
"
" Sections:
"    -> General
"    -> VIM user interface
"    -> Colors and Fonts
"    -> Files and backups
"    -> Text, tab and indent related
"    -> Visual mode related
"    -> Command mode related
"    -> Moving around, tabs and buffers
"    -> Statusline
"    -> Parenthesis/bracket expanding
"    -> General Abbrevs
"    -> Editing mappings
"
"    -> Cope
"    -> Minibuffer plugin
"    -> Omni complete functions
"    -> Python section
"    -> JavaScript section
"
" Plugins_Included:
"     > minibufexpl.vim - http://www.vim.org/scripts/script.php?script_id=159
"       Makes it easy to get an overview of buffers:
"           info -> :e ~/.vim_runtime/plugin/minibufexpl.vim
"
"     > bufexplorer - http://www.vim.org/scripts/script.php?script_id=42
"       Makes it easy to switch between buffers:
"           info -> :help bufExplorer
"
"     > yankring.vim - http://www.vim.org/scripts/script.php?script_id=1234
"       Emacs's killring, useful when using the clipboard:
"           info -> :help yankring
"
"     > surround.vim - http://www.vim.org/scripts/script.php?script_id=1697
"       Makes it easy to work with surrounding text:
"           info -> :help surround
"
"     > snipMate.vim - http://www.vim.org/scripts/script.php?script_id=2540
"       Snippets for many languages (similar to TextMate's):
"           info -> :help snipMate
"
"     > fuzzyfinder - http://www.vim.org/scripts/script.php?script_id=1984
"       Find files fast (similar to TextMate's feature):
"           info -> :help fuzzyfinder@en
"
"  Revisions:
"     > 3.3: Added syntax highlighting for Mako mako.vim 
"     > 3.2: Turned on python_highlight_all for better syntax
"            highlighting for Python
"     > 3.1: Added revisions ;) and bufexplorer.vim
"
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => General
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Sets how many lines of history VIM has to remember
set history=300

" Enable filetype plugin
filetype plugin on
filetype indent on

" Set to auto read when a file is changed from the outside
set autoread

" With a map leader it's possible to do extra key combinations
" like <leader>w saves the current file
let mapleader = ","
let g:mapleader = ","

" Fast saving
nmap <leader>w :w!<cr>

" Fast editing of the .vimrc
map <leader>e :e! ~/.vim_runtime/vimrc<cr>

" When vimrc is edited, reload it
autocmd! bufwritepost vimrc source ~/.vim_runtime/vimrc


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => VIM user interface
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Set 7 lines to the curors - when moving vertical..
set so=7

set wildmenu "Turn on WiLd menu

set ruler "Always show current position

set cmdheight=2 "The commandbar height

set hid "Change buffer - without saving

" Set backspace config
set backspace=eol,start,indent
set whichwrap+=<,>,h,l

set ignorecase "Ignore case when searching

set hlsearch "Highlight search things

set incsearch "Make search act like search in modern browsers

set magic "Set magic on, for regular expressions

set showmatch "Show matching bracets when text indicator is over them
set mat=2 "How many tenths of a second to blink

" No sound on errors
set noerrorbells
set novisualbell
set t_vb=


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Colors and Fonts
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
syntax enable "Enable syntax hl

" Set font according to system
if MySys() == "mac"
  set gfn=Bitstream\ Vera\ Sans\ Mono:h13
  set shell=/bin/bash
elseif MySys() == "windows"
  set gfn=Bitstream\ Vera\ Sans\ Mono:h10
elseif MySys() == "linux"
  set gfn=Monospace\ 10
  set shell=/bin/bash
endif

if has("gui_running")
  set guioptions-=T
  set background=dark
  set t_Co=256
  set background=dark
  colorscheme peaksea

  set nu
else
  colorscheme zellner
  set background=dark
  
  set nonu
endif

set encoding=utf8
try
    lang en_US
catch
endtry

set ffs=unix,dos,mac "Default file types


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Files and backups
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Turn backup off, since most stuff is in SVN, git anyway...
set nobackup
set nowb
set noswapfile


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Text, tab and indent related
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set expandtab
set shiftwidth=4
set tabstop=4
set smarttab

set lbr
set tw=500

set ai "Auto indent
set si "Smart indet
set wrap "Wrap lines

map <leader>t2 :setlocal shiftwidth=2<cr>
map <leader>t4 :setlocal shiftwidth=4<cr>
map <leader>t8 :setlocal shiftwidth=4<cr>


""""""""""""""""""""""""""""""
" => Visual mode related
""""""""""""""""""""""""""""""
" Really useful!
"  In visual mode when you press * or # to search for the current selection
vnoremap <silent> * :call VisualSearch('f')<CR>
vnoremap <silent> # :call VisualSearch('b')<CR>

" When you press gv you vimgrep after the selected text
vnoremap <silent> gv :call VisualSearch('gv')<CR>
map <leader>g :vimgrep // **/*.<left><left><left><left><left><left><left>


function! CmdLine(str)
    exe "menu Foo.Bar :" . a:str
    emenu Foo.Bar
    unmenu Foo
endfunction 

" From an idea by Michael Naumann
function! VisualSearch(direction) range
    let l:saved_reg = @"
    execute "normal! vgvy"

    let l:pattern = escape(@", '\\/.*$^~[]')
    let l:pattern = substitute(l:pattern, "\n$", "", "")

    if a:direction == 'b'
        execute "normal ?" . l:pattern . "^M"
    elseif a:direction == 'gv'
        call CmdLine("vimgrep " . '/'. l:pattern . '/' . ' **/*.')
    elseif a:direction == 'f'
        execute "normal /" . l:pattern . "^M"
    endif

    let @/ = l:pattern
    let @" = l:saved_reg
endfunction



"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Command mode related
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Smart mappings on the command line
cno $h e ~/
cno $d e ~/Desktop/
cno $j e ./
cno $c e <C-\>eCurrentFileDir("e")<cr>

" $q is super useful when browsing on the command line
cno $q <C-\>eDeleteTillSlash()<cr>

" Bash like keys for the command line
cnoremap <C-A>		<Home>
cnoremap <C-E>		<End>
cnoremap <C-K>		<C-U>

cnoremap <C-P> <Up>
cnoremap <C-N> <Down>

" Useful on some European keyboards
map 翻 $
imap 翻 $
vmap 翻 $
cmap 翻 $


func! Cwd()
  let cwd = getcwd()
  return "e " . cwd 
endfunc

func! DeleteTillSlash()
  let g:cmd = getcmdline()
  if MySys() == "linux" || MySys() == "mac"
    let g:cmd_edited = substitute(g:cmd, "\\(.*\[/\]\\).*", "\\1", "")
  else
    let g:cmd_edited = substitute(g:cmd, "\\(.*\[\\\\]\\).*", "\\1", "")
  endif
  if g:cmd == g:cmd_edited
    if MySys() == "linux" || MySys() == "mac"
      let g:cmd_edited = substitute(g:cmd, "\\(.*\[/\]\\).*/", "\\1", "")
    else
      let g:cmd_edited = substitute(g:cmd, "\\(.*\[\\\\\]\\).*\[\\\\\]", "\\1", "")
    endif
  endif   
  return g:cmd_edited
endfunc

func! CurrentFileDir(cmd)
  return a:cmd . " " . expand("%:p:h") . "/"
endfunc


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Moving around, tabs and buffers
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Map space to / (search) and c-space to ? (backgwards search)
map <space> /
map <c-space> ?
map <silent> <leader><cr> :noh<cr>

" Smart way to move btw. windows
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l

" Close the current buffer
map <leader>bd :Bclose<cr>

" Close all the buffers
map <leader>ba :1,300 bd!<cr>

" Use the arrows to something usefull
map <right> :bn<cr>
map <left> :bp<cr>

" Tab configuration
map <leader>tn :tabnew %<cr>
map <leader>te :tabedit 
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove 

" When pressing <leader>cd switch to the directory of the open buffer
map <leader>cd :cd %:p:h<cr>


command! Bclose call <SID>BufcloseCloseIt()
function! <SID>BufcloseCloseIt()
   let l:currentBufNum = bufnr("%")
   let l:alternateBufNum = bufnr("#")

   if buflisted(l:alternateBufNum)
     buffer #
   else
     bnext
   endif

   if bufnr("%") == l:currentBufNum
     new
   endif

   if buflisted(l:currentBufNum)
     execute("bdelete! ".l:currentBufNum)
   endif
endfunction

" Specify the behavior when switching between buffers 
try
  set switchbuf=usetab
  set stal=2
catch
endtry


""""""""""""""""""""""""""""""
" => Statusline
""""""""""""""""""""""""""""""
" Always hide the statusline
set laststatus=2

" Format the statusline
set statusline=\ %F%m%r%h\ %w\ \ CWD:\ %r%{CurDir()}%h\ \ \ Line:\ %l/%L:%c


function! CurDir()
    let curdir = substitute(getcwd(), '/Users/amir/', "~/", "g")
    return curdir
endfunction


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Parenthesis/bracket expanding
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
vnoremap $1 <esc>`>a)<esc>`<i(<esc>
vnoremap $2 <esc>`>a]<esc>`<i[<esc>
vnoremap $3 <esc>`>a}<esc>`<i{<esc>
vnoremap $$ <esc>`>a"<esc>`<i"<esc>
vnoremap $q <esc>`>a'<esc>`<i'<esc>
vnoremap $e <esc>`>a"<esc>`<i"<esc>

" Map auto complete of (, ", ', [
inoremap $1 ()<esc>i
inoremap $2 []<esc>i
inoremap $3 {}<esc>i
inoremap $4 {<esc>o}<esc>O
inoremap $q ''<esc>i
inoremap $e ""<esc>i


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => General Abbrevs
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
iab xdate <c-r>=strftime("%d/%m/%y %H:%M:%S")<cr>


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Editing mappings
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Remap VIM 0
map 0 ^

"Move a line of text using ALT+[jk] or Comamnd+[jk] on mac
nmap <M-j> mz:m+<cr>`z
nmap <M-k> mz:m-2<cr>`z
vmap <M-j> :m'>+<cr>`<my`>mzgv`yo`z
vmap <M-k> :m'<-2<cr>`>my`<mzgv`yo`z

if MySys() == "mac"
  nmap <D-j> <M-j>
  nmap <D-k> <M-k>
  vmap <D-j> <M-j>
  vmap <D-k> <M-k>
endif

"Delete trailing white space, useful for Python ;)
func! DeleteTrailingWS()
  exe "normal mz"
  %s/\s\+$//ge
  exe "normal `z"
endfunc
autocmd BufWrite *.py :call DeleteTrailingWS()


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Cope
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Do :help cope if you are unsure what cope is. It's super useful!
map <leader>cc :botright cope<cr>
map <leader>n :cn<cr>
map <leader>p :cp<cr>


""""""""""""""""""""""""""""""
" => bufExplorer plugin
""""""""""""""""""""""""""""""
let g:bufExplorerDefaultHelp=0
let g:bufExplorerShowRelativePath=1


""""""""""""""""""""""""""""""
" => Minibuffer plugin
""""""""""""""""""""""""""""""
let g:miniBufExplModSelTarget = 1
let g:miniBufExplorerMoreThanOne = 2
let g:miniBufExplModSelTarget = 0
let g:miniBufExplUseSingleClick = 1
let g:miniBufExplMapWindowNavVim = 1
let g:miniBufExplVSplit = 25
let g:miniBufExplSplitBelow=1

let g:bufExplorerSortBy = "name"

autocmd BufRead,BufNew :call UMiniBufExplorer

map <leader>u :TMiniBufExplorer<cr>:TMiniBufExplorer<cr>


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Omni complete functions
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
autocmd FileType css set omnifunc=csscomplete#CompleteCSS


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Spell checking
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"Pressing ,ss will toggle and untoggle spell checking
map <leader>ss :setlocal spell!<cr>

"Shortcuts using <leader>
map <leader>sn ]s
map <leader>sp [s
map <leader>sa zg
map <leader>s? z=


""""""""""""""""""""""""""""""
" => Python section
""""""""""""""""""""""""""""""
au FileType python set nocindent
let python_highlight_all = 1
au FileType python syn keyword pythonDecorator True None False self

au BufNewFile,BufRead *.jinja set syntax=htmljinja
au BufNewFile,BufRead *.mako set ft=mako

au FileType python inoremap <buffer> $r return 
au FileType python inoremap <buffer> $i import 
au FileType python inoremap <buffer> $p print 
au FileType python inoremap <buffer> $f #--- PH ----------------------------------------------<esc>FP2xi
au FileType python map <buffer> <leader>1 /class 
au FileType python map <buffer> <leader>2 /def 
au FileType python map <buffer> <leader>C ?class 
au FileType python map <buffer> <leader>D ?def 


""""""""""""""""""""""""""""""
" => JavaScript section
"""""""""""""""""""""""""""""""
au FileType javascript call JavaScriptFold()
au FileType javascript setl fen
au FileType javascript setl nocindent

au FileType javascript imap <c-t> AJS.log();<esc>hi
au FileType javascript imap <c-a> alert();<esc>hi

au FileType javascript inoremap <buffer> $r return 
au FileType javascript inoremap <buffer> $f //--- PH ----------------------------------------------<esc>FP2xi

function! JavaScriptFold() 
    setl foldmethod=syntax
    setl foldlevelstart=1
    syn region foldBraces start=/{/ end=/}/ transparent fold keepend extend

    function! FoldText()
    return substitute(getline(v:foldstart), '{.*', '{...}', '')
    endfunction
    setl foldtext=FoldText()
endfunction


""""""""""""""""""""""""""""""
" => Fuzzy finder
""""""""""""""""""""""""""""""
try
    call fuf#defineLaunchCommand('FufCWD', 'file', 'fnamemodify(getcwd(), ''%:p:h'')')
    map <leader>t :FufCWD **/<CR>
catch
endtry


""""""""""""""""""""""""""""""
" => Vim grep
""""""""""""""""""""""""""""""
let Grep_Skip_Dirs = 'RCS CVS SCCS .svn generated'
set grepprg=/bin/grep\ -nH


"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => MISC
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Remove the Windows ^M - when the encodings gets messed up
noremap <Leader>m mmHmt:%s/<C-V><cr>//ge<cr>'tzt'm

"Quickly open a buffer for scripbble
map <leader>q :e ~/buffer<cr>

by 紅塵一隅間拾得

http://greenisland.csie.nctu.edu.tw/wp/category/comuter/vim/

http://greenisland.csie.nctu.edu.tw/wp/2005/09/02/302/

作者: chrisliu (ChrisLiu*) 站內: Unix
標題: [vim] vim 的取代置換功能「s」
時間: 2006/08/07 Mon 03:16:46

在前面我們所談的那些可以說是比較基本的東西,但是對於一份文件來說,光有前面所介紹的游標移動、刪除等等功能是不足夠的。面對一份文件我們通常會因為某些緣故而使得我們必須去修改當中固定出現的字串樣式(pattern)成我們想要的樣子。最常遇到的就像中文文件的標點符號問題,或是 unix 和 DOS 文件格式之間轉換常會有個 ^M 結尾會讓人覺得很討厭,又或是我們想要把一份 HTML 格式的文件去除掉它的 HTML tag。

對於這些事情來說,拿中文標點符號置換這個很多編輯器都做得到,簡單地說如果想更動的 pattern 是一個固定的字串,那對於一般編輯器來說都不會太困難,但是對於具有固定格式,但字串內容卻不一定的該怎麼辦?就像要去掉 HTML 格式中的所有 HTML tag?這就是 vim 開始大顯身手的地方了。

今天我們不談別的其他指令,就光談在 vim 中的「 :s 」指令。小寫 :s 表示置換(substitute)的意思,不過通常你用 vim 下 :h :s 指令的時候會看到這樣的畫面:

vim help for :s substitute

其實這一串東西就是在說 :s 這個指令的格式要怎麼下。

Range:

一般對於整份文件都要作置換的話,我都會下像這樣的指令:

:%s/, /,/g

最前面的「%」就是表示全域,也就是現在編輯的這一份文件都要作後面取代的工作。那這個指令就是說要把半形的逗點「,」變成全形「,」。那後面「g」又代表什麼意思呢?在 g 這個欄位上的東西是用來表示對目前這個指令所做的額外的選項。就拿 g 來說,g 代表在文件中每一個出現的半形逗點都要置換成全形。或許你會問剛剛不是已經用「%」表示全域了嗎,怎麼又要用 g 呢?我應該這樣說,「%」用來表示從文件的第一行到最後一行。但是在比對(match)的時候,如果不加「g」這個額外選項的話, vim 只會把每一行比對到的第一個作取代,同行其他也 match 到的就不管了。所以用「g」表示每一行中每一個比對到的都要置換。

所以同理,如果你要把那些因為 un*ix 和 DOS 之間格式不合所造成的^M消掉的話,也只需要下成這樣就可以了:

  :%s/^M//g

可是有時候你想要作置換的只是文件中的某一部份的話怎麼辦?不要緊,還記得選取模式嗎?在你想置換部分的開頭按下大寫「V」然後用移動游標(我們之前講的 vim 移動游標的方法在選取模式下都可以用)到你想要的位置之後按「:」就會跳到輸入指令的狀態,如下圖最下面那行看到的一樣:

vim selection for substitute

當然你很確定行數,你也可以這樣下:

:1,300s/vim/VIM/g

或者是如果你很確定要從現在游標所在行之後的所有行都置換,可以下成:

:.,$s/vim/VIM/g

冒號一開頭的那一小點「 . 」就代表游標現在所在行,「$」則用來表示最後一行。

或許聰明的你已經想到怎麼樣可以從現在所在行之前的都要置換了,

:.,1s/vim/VIM/g

不過當你這樣打的時候, vim 會跳出來一個訊息:

Backwards range given, OK to swap (y/n)?

這就是說你給了一個起始行數比結束行數還要大的範圍。這是因為 vim 所定的範圍都是從小到大,如果你要從大到小不是不行,只是多個訊息確認你沒有打錯罷了。

Pattern:

像前面說,固定字串像把半形逗點換成全形逗點這都還容易,如果只是格式固定,但是字串內容會變動怎麼辦?就像去 HTML tag 的時候就很麻煩。

還記得我們在淺談vim那時候提過的指令嗎?

  * :%s/\n/^V/g
  * :%s/< [^<>]*>//g
  * :%s/^V/\n/g

在中間的那一些 [^<>]*看起來像外星文字的,就是 pattern 比對的主力。事實上關於這些東西,我們在談 vim 的 search 搜尋功能的時候也有提到過一些。所以我們今天就來補一些上次沒有講到的東西。

假如我現在有一筆人名、電話的資料,由於是隨手記的,上面自然就是沒有排序過。那沒排序過對於想要在上面找資料的人就很麻煩。萬一人名記不太清楚,電話號碼也記得七七八八,雖然說有 vim 方便的 search 功能,但總是感覺不足。(當然這只是假設情況,因為實際上可能大家都已經建立某種方便搜尋的資料庫了)

我們先假設人名、電話的對應長成這樣:

趙大明 1235478982
錢小名 1223450012
王孫李 5938123812
周渚衛 1384914191
沈以情 2345934981

那我可不可以讓它變成這樣子?

1235478982 趙大明
1223450012 錢小名
5938123812 王孫李
1384914191 周渚衛
2345934981 沈以情

我可以下這樣的指令完成這個工作:

:%s/\([^0-9]\{1,}\)\([0-9]\{1,}\)/\2 \1/g

前面橘色的部分 \([^0-9]\{1,}\) 用 \( \) 括起來的,表示這是一個的單元,之後就可以依照它出現的順序而使用 \1, \2,… ,來代表它。所以我們可以看到 [^0-9] 就表示非數字的部分,後面的\{1,} 如果你還記得的話,就是代表出現至少一次。不過這個時候DK長輩會跟你說用 vim 要文明一點,要用「\+」來代表至少出現一次。看個人喜好了,如果你願意多記一些代替的符號就多記一點,你可以用 :h /multi 看到更多這些替代符號。

所以把 pattern 用 \( \) 分開之後,我們就可以用 \1,\2 來把他們交換位置。

不過你可能會說這樣還沒排序啊。我們可以用選取模式把整份文件選起來,或是你懶得用上下左右改變,你可以用 ggVG (gg 跳到第一行之後,用大寫V進入選擇模式,以大寫G跳到最後一行)把整份文件選起來之後按 :!sort,這時候在你 vim 視窗的最底下就會變成這樣:

:』< [^<>]*>!sort

按下去就會變成根據每一行的最前頭作排序的結果。所以結果就會變成:

1223450012 錢小名
1235478982 趙大明
1384914191 周渚衛
2345934981 沈以情
5938123812 王孫李

很簡單吧? :p

如果你願意配合暫存器( registers )的話,有時候也能省點力氣。在講 vim search 的時候,我們曾經提了用 搭配數字鍵 0 來把暫存器 0 的東西叫出來。同樣的,我們不管用 / 或是 ? 等等輸入字串的時候,事實上都已經把要搜尋的字串寫入「/」的暫存器裡面,所以當我們只是想置換的字串就是搜尋的字串的話,我們可以這樣做:

:%s//用來取代的字串/g

表示在按 之後按下「/」這個按鍵。這樣就可以把搜尋的字串叫出來並用之於置換指令上。

額外指令:

我們剛剛在前面談到可以作像「g」這些的額外控制。那有哪些控制可以作呢?

比方說在我們作置換的時候,由於 vim 預設是有大小寫的差別,如果你不管大小寫都要取代的話,那可以用「i」這個額外參數來控制 vim 取代的時候就不管大小寫都會作取代的工作。

不過有時候,我們可能不太能確定是不是整份文件中的每一個都要取代,那我們就可以加「c」 confirm 確認參數來控制,那使用上也很容易。 vim 會在比對到之後問

(y/n/a/q/l/^E/^Y)?

對於 :s 的用法到這裡我們就已經把常用的幾個方式都說完了。礙於篇幅,我也決定先寫到這裡就好,不然寫一大篇,可能連有興趣進來瞭解 vim 的人光看到就害怕了,怎麼還有辦法體會 vim 的好呢?其實關於 :s 的用法,還有 pattern 還有很多的方式在本篇中沒有提到,你可以在 vim 中用 :h :s 看到更多詳細的資料。今天就來 vim 吧!

Vrapper

Vim-like editing in Eclipse

http://vrapper.sourceforge.net/home/

VIM Color Scheme Test - Perl

http://vimcolorschemetest.googlecode.com/svn/html/index-pl.html

1) 若字串中出現 '/',使用 '\/' 跳脫
2) 例:「:tabdo %s/foo/bar/g」