Logo
Published on

Vim 搜尋技巧:快速定位與取代

Vim 系列文章

  1. Vim 生存指南:模式與移動
  2. Vim 編輯基礎:輸入、刪除和複製貼上
  3. Vim 選取模式:三種 Visual Mode
  4. Vim 語法系統:動詞 + 量詞 + 名詞
  5. Vim 搜尋技巧:快速定位與取代 (本篇)
  6. Vim 效率倍增:重複與自動化
  7. Vim 客製化:設定與 IDE 整合

前幾篇學了基本移動像 h/j/k/lw/b,但一步一步移動有點慢。這篇要學習用搜尋快速跳到目標字元

單行搜尋:f / t / F / T

與其一步一步移動,不如直接「跳」到目標字元

f:向後找,停在字元上

f{char} = find character

find the first f here
^                        ← 起點

按 ft(找 t)
find the first f here
     ^                   ← 停在第一個 t 上

t:向後找,停在字元前

t{char} = until character

find the first f here
^                        ← 起點

按 tt(找 t)
find the first f here
    ^                    ← 停在 t 的「前一格」

f vs t:關鍵差異

指令停在哪使用場景
f字元想移動到某個字元
t字元想操作到某個字元「之前」

實用範例:刪除到括號前

delete(this)
^

使用 df(
this)刪到 ( 包含 (

使用 dt(
(this)刪到 ( 之前,不包含 (

這就是 t 的威力:配合 dc,可以精準地刪到/改到某個字元「之前」

F / T:向前(往左)找

大寫版本是向前搜尋

指令方向停在哪
f→ 向後字元上
F← 向前字元上
t→ 向後字元前
T← 向前字元後
find the first f here
                    ^    ← 起點(在 e 上)

Ft(往左找 t)
find the first f here
             ^           ← 停在 t 上

Tt(往左找 t)
find the first f here
              ^          ← 停在 t 的「後一格」

;,:重複搜尋

指令動作
;重複上次的 f/t/F/T(同方向)
,反方向重複
a b c d e f g
^              ← 起點

按 f 空格跳到第一個空格
a b c d e f g
 ^

; 跳到下一個空格
a b c d e f g
   ^

; 再跳
a b c d e f g
     ^

, 反方向跳回去
a b c d e f g
   ^

數字 + f/t

3f空格   → 跳到第 3 個空格
2fa      → 跳到第 2 個 a

全文搜尋:/?

單行搜尋只能在當前行內找,如果要在整個檔案中搜尋,就要用 /?

基本搜尋

指令方向
/{pattern}向後搜尋
?{pattern}向前搜尋
n跳到下一個結果(同方向)
N跳到上一個結果(反方向)
1 hello world
  ^(游標在第 1 行的 h)
2 hello again
3 say hello

/hello Enter

1 hello world
2 hello again
  ^            ← 跳到第 2 行的 hello
3 say hello

按 n

1 hello world
2 hello again
3 say hello
      ^        ← 跳到第 3 行的 hello

N

1 hello world
2 hello again
  ^            ← 跳回第 2 行的 hello
3 say hello

搜尋當前單字:*#

指令動作
*向後搜尋游標下的單字
#向前搜尋游標下的單字

這很實用。想找某個變數在哪裡被用到,只要把游標放在上面,按 * 就可以了

1 hello world
        ^(游標在 world 的 w 上)
2 say world
3 world cup

*

1 hello world
2 say world
      ^        ← 跳到第 2 行的 world
3 world cup

按 n

1 hello world
2 say world
3 world cup
  ^            ← 跳到第 3 行的 world

按 #

1 hello world
2 say world
      ^        ← 跳回第 2 行的 world
3 world cup

找到後可以按 n 繼續往下找,N 往上找。也可以一直按 *# 來跳到下一個或上一個

搜尋取代

基本取代

:s/old/new/         → 當前行第一個 old 換成 new
:s/old/new/g        → 當前行所有 old 換成 new
:%s/old/new/g       → 整個檔案所有 old 換成 new
:%s/old/new/gc      → 整個檔案,每次詢問確認

取代的 flags

Flag意義
gglobal,該行所有符合的都取代
cconfirm,每次確認
iignore case,忽略大小寫
I不忽略大小寫(強制區分)

使用 c flag 時,每次找到匹配會出現確認提示:

Replace with XXX (y/n/a/q/l)?
選項意義
yyes,取代這個
nno,跳過這個
aall,取代所有剩餘的(不再詢問)
qquit,退出取代
llast,取代這個然後退出

範圍取代

:5,10s/old/new/g    → 第 5-10 
:.,+5s/old/new/g    → 當前行到往下 5 
:'<,'>s/old/new/g   → Visual Mode 選取範圍

排序

:sort       → 整個檔案按字母排序
:sort!      → 反向排序(Z-A
:sort n     → 按數字排序
:sort u     → 排序並移除重複行
:'<,'>sort  → 只排序選取範圍
1 cherry
2 apple
3 banana

 :%sort

1 apple
2 banana
3 cherry

實用取代範例

刪除所有行尾空格

:%s/\s\+$//g

搜尋 + 動詞組合

搜尋不只是用來移動,還可以搭配動詞使用

d/foo     → 刪除到 "foo" 之前
c/bar     → 修改到 "bar" 之前
y/baz     → 複製到 "baz" 之前

這和 dt{char} 類似,但可以搜尋多個字元

1 function hello() {
  ^(游標在第 1 行的 f)
2   console.log("hello");
3   return "hello world";
4 }

按 d/return

1 return "hello world";
  ^
2 }

跨行刪除:從第 1 行的 f 刪除到第 3 行的 return 之前,中間的內容全部被刪掉

本篇重點整理

單行搜尋
  f{char} → 向後找,停在字元上
  t{char} → 向後找,停在字元前
  F/T     → 向前找
  ;       → 重複上次搜尋
  ,       → 反向重複

全文搜尋
  /{pattern} → 向後搜尋
  ?{pattern} → 向前搜尋
  n/N        → 下一個/上一個
  *          → 搜尋游標下的單字(向後)
  #          → 搜尋游標下的單字(向前)

搜尋取代
  :s/old/new/    → 當前行第一個
  :s/old/new/g   → 當前行全部
  :%s/old/new/g  → 整個檔案
  :%s/old/new/gc → 整個檔案,逐一確認

搜尋 + 動詞
  d/pattern → 刪除到搜尋結果之前
  c/pattern → 修改到搜尋結果之前

圖片來源:AI 產生