文本替換 (:s)
這是 Vim 中最強大和最常用的進階功能之一。
基本語法: :[range]s/old/new/[flags]
-
[range]: 指定替換操作的範圍。省略時默認為當前行。%:整個文件 (例如:%s/old/new/)5,10:第5行到第10行 (例如:5,10s/old/new/).,$:從當前行到文件末尾 (例如:.,$s/old/new/).+1,$-1:從當前行下一行到文件倒數第二行/pattern1/,/pattern2/:從匹配pattern1的行到匹配pattern2的行'<,'>:當前選中的可視區域(在可視模式下按:後自動填充)
s: substitute (替換) 命令。old: 要被替換的文本(模式)。支持正則表達式! (這是它強大的核心)new: 替換成的新文本。-
[flags]: 控制替換行為的標誌(可選,可組合使用)。g (global): 對一行內的所有匹配項進行替換(默認只替換一行中的第一個匹配項)。非常重要!c (confirm): 每次替換前要求確認。按y替換,n跳過,a替換所有,q退出替換。i (ignore case): 忽略大小寫進行匹配。I (no ignore case): 區分大小寫進行匹配(默認行為)。e (no errors): 如果old沒有匹配項,不報錯(抑制錯誤信息)。
常見示例:
- 替換當前行第一個
foo為bar::s/foo/bar/ - 替換當前行所有
foo為bar::s/foo/bar/g - 替換整個文件中所有
foo為bar(全局替換)::%s/foo/bar/g - 替換第 10 行到第 20 行所有
foo為bar::10,20s/foo/bar/g - 替換整個文件中所有
foo為bar,但每次替換前確認::%s/foo/bar/gc - 將文件中所有
color或colour替換為hue(忽略大小寫)::%s/colou\?r/hue/gi(這裏\?表示前面的u可有可無,i忽略大小寫) - 刪除所有行尾的空白字符:
:%s/\s\+$//g(\s\+匹配一個或多個空白字符,$匹配行尾) - 刪除所有行首的空白字符:
:%s/^\s\+//g(^匹配行首) - 將
"name"替換為'name'::%s/"$$[^"]*$$"/'\1'/g(使用捕獲組$$...$$和反向引用\1) - 在變量名後添加
_v2(捕獲組\1)::%s/\<\(\w\+\)\>/\1_v2/g
重要提示:
- 正則表達式是核心: 要充分利用
:s,必須學習基礎的正則表達式 (Vim使用自己的變種,但基礎與其他類似)。 - 分隔符
/可替換: 如果old或new中包含/,可以用其他字符作為分隔符,如:s#old#new#g或:s@old@new@g。 - 先確認 (
c標誌): 對於全局替換 (:%s/...),尤其是在生產代碼中,強烈建議使用c標誌先檢查確認。 - 查看匹配: 在輸入
:s/old後,按Ctrl-R Ctrl-W(在命令模式下) 可以將光標下的單詞插入到命令中。在替換前使用/old搜索一下,用:nohl取消高亮,可以直觀看到哪些地方會被匹配。
批量操作/多文件操作
多行編輯(可視化塊模式)
結合 Ctrl + v(垂直選中)實現批量添加 / 刪除前綴 / 後綴:
-
批量給多行添加前綴(如註釋符號
//):- 按
Ctrl + v進入垂直選擇模式 - 移動光標選中需要操作的行(如向下按
j選 5 行) - 按
I(大寫I,進入插入模式),輸入前綴(如//) - 按
ESC,所有選中行都會添加前綴
- 按
-
批量刪除多行前綴:
Ctrl + v選中需要刪除的前綴列(如前 2 個字符)- 按
d直接刪除選中的列
argdo / bufdo / windo / tabdo:
- 這些命令允許在多個參數列表文件(
argdo)、緩衝區(bufdo)、窗口(windo)、標籤頁(tabdo) 上執行相同的Ex命令。 -
示例:
- 打開多個文件:
vim *.txt -
在所有打開的
.txt文件中替換old為new::argdo %s/old/new/ge | update%s/old/new/ge:在每個文件內執行全局替換 (g),忽略錯誤 (e防止沒有匹配的文件報錯退出)。| update:管道符|連接命令,update僅在文件被修改過時才保存。
- 在所有打開的緩衝區中執行替換並保存:
:bufdo %s/old/new/ge | w
- 打開多個文件:
- 注意:
argdo操作的是:args列表中的文件,bufdo操作的是所有加載到緩衝區的文件。
:vimgrep / :grep:
- 在整個項目文件中搜索包含特定模式的行。
-
:vimgrep /pattern/[j][g] file(s)/pattern/:搜索模式(支持Vim強大的正則)。[j]:不跳轉到第一個匹配項(靜默搜索)。[g]:每行只列出一次匹配(默認列出每行的所有匹配)。file(s):文件模式,如**/*.py遞歸搜索所有.py文件。- 示例:
:vimgrep /TODO/ **/*.py(在所有.py文件中搜索"TODO")
- 搜索結果會填充到
quickfix列表 (:copen打開列表,:cclose關閉,:cn下一個,:cp上一個)。 -
結合
:cdo/:cfdo::cdo command:對quickfix列表中的每一行執行命令 (光標會移動到對應行)。:cfdo command:對quickfix列表中的每一個文件執行命令 (光標會移動到對應文件)。-
強大示例: 在所有包含
"TODO"的.py文件中,將"TODO"替換為"FIXME"::vimgrep /TODO/ **/*.py:cfdo %s/TODO/FIXME/ge | update- 對每個匹配文件 (
:cfdo) 執行全局替換 (%s/.../g),忽略錯誤 (e),修改才保存 (update)。
宏錄製 (q):
- 錄製:
q + <register>(例如qa) 開始錄製到寄存器a-> 執行你的操作序列 ->q停止錄製。 - 播放:
@ + <register>(例如@a) 播放寄存器a中的宏。@@重複播放上一次播放的宏。 -
批量播放: 結合行號或可視選擇。
:10,20 normal @a:對第 10 行到第 20 行的每一行,在普通模式下執行寄存器a中的宏。- 在可視模式下選中多行,然後按
:,會自動填充為:'<,'>,然後輸入normal @a。
-
示例: 給一組連續的行添加註釋 (
//):- 將光標移動到第一行的行首。
qa開始錄製到a。I// <Esc>:進入插入模式,輸入//,退出插入模式。j:移動到下一行。q:停止錄製。- 按
@a對當前行執行宏(添加註釋並下移一行)。 - 按
5@a重複執行 5 次宏(給接下來的 5 行添加註釋)。或者用jVG選中剩餘行,然後:'<,'>normal @a。
其他高級技巧
重複操作(.命令)
. 可以重複上一次的編輯操作,是 Vim 最被低估的技巧之一:
- 例 1:刪除一行後,按
.會重複刪除下一行 - 例 2:在某行末尾添加
;,按.會在其他行末尾重複添加
快速跳轉與定位
-
按內容跳轉:
*:向下跳轉到當前單詞的下一個匹配#:向上跳轉到當前單詞的上一個匹配
-
跳轉到上次編輯位置:
''(兩個單引號):跳回上一次跳轉前的位置.(點符號):跳轉到上次編輯的位置
global 命令 (:g):
- 對匹配特定模式的行執行命令。
- 語法:
:[range]g/pattern/command -
示例:
- 刪除所有空行:
:g/^$/d(匹配行首^緊接着行尾$的行,即空行,執行d刪除)。 - 刪除所有包含
DEBUG的行::g/DEBUG/d - 將所有包含
TODO的行復制到文件末尾::g/TODO/t$(t是copy的縮寫,$表示文件末尾)。 - 在包含
function的行前面添加註釋::g/function/normal O// TODO: Implement
- 刪除所有空行:
全局反向操作(:vglobal)
:v/^$/d:刪除所有非空行
寄存器 (") 的高級使用:
| 寄存器 | 含義 |
|---|---|
" |
默認寄存器,存放最近一次的刪除或複製 |
0 |
存放最近一次的複製(y 命令) |
1–9 |
最近 9 次刪除操作 (滾動存放) |
a–z |
用户自定義寄存器,可用 "ayy 複製到 a |
/: |
存放最近一次的搜索模式 |
-
指定寄存器: 在操作命令前加上
"<register>。"ayy:複製當前行到寄存器a。"bdd:刪除當前行到寄存器b(剪切)。"ap:粘貼寄存器a的內容。
- 查看寄存器內容:
:reg或:reg <register>(如:reg a)。 -
系統剪貼板 (
"+ / "*): 設置了clipboard=unnamed,通常"+和"*都指向系統剪貼板。顯式使用:"+yy:複製當前行到系統剪貼板。"+p:粘貼系統剪貼板內容到Vim。
-
只讀寄存器:
"%:當前文件名。".:上次插入的文本。"::上次執行的命令。"/:上次搜索的模式。
摺疊代碼
zc:摺疊當前代碼塊(如函數、循環)zo:展開當前摺疊塊zR:展開所有摺疊zM:摺疊所有代碼塊
(需先設置摺疊方式:set foldmethod=indent 按縮進摺疊,或 set foldmethod=syntax 按語法摺疊)
顯示不可見字符
查看空格、製表符、換行符等:
:set list " 顯示不可見字符($表示換行,^I表示製表符)
:set nolist " 關閉顯示
標記 (Marks):
- 快速跳轉到文件中的特定位置。
- 設置標記:
m + <letter>(例如ma設置標記a)。 - 跳轉到標記:
` + <letter>
(反引號,例如 `a 精確跳轉到標記 a 的行和列) 或
' + <letter>
(單引號,例如 'a 跳轉到標記 a 所在行的行首)。
- 查看標記:
:marks。 -
特殊標記:
- ``:跳回上次跳轉前的位置。
- '.:上次修改的行。
- '^:上次插入模式退出的位置。
會話管理 (Sessions)
- 保存會話(打開的文件、窗口布局等):
:mksession ~/session.vim
- 恢復會話:
vim -S ~/session.vim
外部命令與管道
- 在
Vim中執行shell命令並將結果導入緩衝區:
:r !ls -l
- 對選中區域執行外部命令:
:'<,'>!sort
將選區內內容按 sort 排序。
自動命令 (autocmd):
- 在特定事件發生時自動執行命令,用於高度定製
Vim行為(如文件類型檢測、保存時自動格式化等)。這屬於更高級的.vimrc配置。 - 基本示例 (在
.vimrc中):
" 當打開或新建 .py 文件時設置縮進
autocmd BufNewFile,BufRead *.py setlocal tabstop=4 shiftwidth=4 expandtab
" 保存 .py 文件前自動刪除行尾空白
autocmd BufWritePre *.py :%s/\s\+$//e
窗口和標籤頁管理:
-
分割窗口:
:split / :sp [filename]:水平分割當前窗口(或打開文件)。:vsplit / :vsp [filename]:垂直分割當前窗口(或打開文件)。Ctrl-w s:水平分割。Ctrl-w v:垂直分割。Ctrl + w + =:讓所有分屏高度 / 寬度相等
- 窗口間跳轉:
Ctrl-w h/j/k/l/Ctrl-w w(循環)。 - 關閉窗口:
:close/Ctrl-w c。 - 調整窗口大小:
Ctrl-w +/Ctrl-w -(高度),Ctrl-w >/Ctrl-w <(寬度)。 -
標籤頁:
:tabnew [filename]:在新標籤頁打開文件。:tabclose:關閉當前標籤頁。:tabnext / gt:下一個標籤頁。:tabprevious / gT:上一個標籤頁。:tabm [n]:移動當前標籤頁到位置n(從 0 開始計數)。
命令行窗口 (q:):
- 普通模式下按
q:打開命令行窗口。這裏顯示命令歷史,可以像編輯普通文本一樣瀏覽、修改歷史命令,然後按回車執行選中的命令。非常方便修改複雜命令(如帶複雜正則的:s命令)。 -
表達式寄存器 (
=):- 在插入模式下按
Ctrl-r =,可以輸入一個 Vim 表達式(如2+2或@a),計算結果會插入到文本中。高級用法可以結合函數。
- 在插入模式下按
-
normal命令 (:normal):- 在命令行模式下執行普通模式的命令序列。
-
示例:
- 在當前行執行宏
a::normal @a - 在選中的行(可視模式後)刪除行首空白:
:'<,'>normal ^dW(先跳到行首非空字符^,然後刪除一個單詞dW,這裏空白被當作一個單詞)。
- 在當前行執行宏
-
符號自動補全 (
Ctrl-x系列):-
在插入模式下:
Ctrl-x Ctrl-l:整行補全。Ctrl-x Ctrl-f:文件名補全。Ctrl-x Ctrl-o:全能 (Omni) 補全(需要文件類型支持,如編程語言)。Ctrl-n / Ctrl-p:使用當前緩衝區中的單詞補全。
-
-
自動縮進 (
=):- 在可視模式下選中代碼塊,按
=會自動縮進(根據文件類型和你的indent設置)。 gg=G:對整個文件進行自動縮進 (gg到文件頭,=縮進操作,G到文件尾)。
- 在可視模式下選中代碼塊,按
高級配置技巧(需修改.vimrc)
高效搜索
set incsearch:輸入搜索詞時實時高亮匹配set hlsearch:高亮所有搜索結果,用:nohl臨時關閉高亮
文件管理
set autochdir:自動切換工作目錄到當前文件位置set wildmenu:增強文件名補全(按Tab循環選擇)
備份與撤銷
set undodir=\~/.vim/undo:持久化撤銷歷史(支持關閉文件後仍可撤銷)
代碼格式化
filetype indent on:根據文件類型自動縮進set tabstop=4:設置Tab為4空格
插件推薦(進階工具)
- 多文件搜索:
fzf.vim(模糊搜索文件/內容) - 批量註釋:
vim-commentary(gc快速註釋) - 環繞編輯:
vim-surround(cs"'替換雙引號為單引號) - 自動補全:
coc.nvim(LSP支持) - 項目目錄樹瀏覽、文件管理。
nerdtree -
實時顯示
Git diff(新增、修改、刪除行)vim-gitgutter / signify
其他示例
將項目中的 user_id 改為 user_id_new:
- 精確全文替換:
:%s/\<user_id\>/user_id_new/gc
- 如果涉及多個文件:
:argdo %s/\<user_id\>/user_id_new/ge | update
關鍵點:
\<和\>匹配單詞邊界(避免匹配_user_id_old)/e屏蔽未匹配時的報錯| update只保存修改過的文件