vim global
:global
命令是 Vim 中一個更強大的命令 (之一)。它允許你找到一個匹配點並且在那裡執行一個命令。它的一般形式是:
:[range]g/{pattern}/{command}
在每一匹配行上執行命令command. 這個命令只能是冒號命令, 普通模式命令不能在這裡使用。如果需要,可以使用:normal
命令。
如果要檢視可以使用的命令,可以help ex-cmd-index
。 如果要檢視詳細解釋, 檢視help 10.4
和 help multi-repeat
。
vglobal
相當於global!
, 兩者可以組合使用, 如:g/found/v/notfound/{cmd}
利用global
我們可以把我們之前學的很多東西都串連起來,以完全一些非常奇妙的動作。
所以下面我們通過示例來學習global
的用法。
示例
示例一
用法: 顯示匹配行上下共3行, 第二寫法能更清晰的看到上下3行
:g/patttern/z#.3
:g/pattern/z#.3|echo "========"
關於z的用法,可以輸入help :z
, 如下所示
:{range}z[+-^.=]{count}
顯示包圍 {range} 指定行的若干行文字,如果沒有 {range},顯示當前行上下的文字。如果有 {count},它指定 你能看到的行數。否則,如果只有一個視窗,使用 'scroll' 選項值的兩倍。再不然,使用當前的視窗大小減 3。
如果提供了 {count},'window' 選項會被設為該值。
:z
可以單獨使用,也可以後跟數個標點符號中的一個。他們有如下的效果:
標記 | 首行 | 末行 | 新游標行 |
---|---|---|---|
+ | 當前行 | 向前 1 屏 | 向前 1 屏 |
- | 向後 1 屏 | 當前行 | 當前行 |
^ | 向後 2 屏 | 向後 1 屏 | 向後 1 屏 |
. | 向後 1/2 屏 | 向前 1/2 屏 | 向前 1/2 屏 |
= | 向後 1/2 屏 | 向前 1/2 屏 | 當前行 |
不指定任何標記相當於指定 "+"。如果標記是 "=",當前行會 被連字元組成的兩行包圍。
:{range}z#[+-^.=]{count}
和 ":z" 類似,但顯示行號。
示例二
用法: 刪除所有匹配行 或 所有不匹配行
:g/pattern/d
:g!/pattern/d
:v/pattern/d
g!
和v
是等價的。
這個例子的一個用法就是刪除所有空行
:g/^\s*$/d
示例三
用法: 在所有行之間加上空行
:g/^/pu \"\n\"
關於pu
的用法,可以輸入:help :put
:[line]pu[t] [x]
放置文字 [從暫存器 x] 在行號 [line] (預設為當前行) 之後。它總是 |linewise| 行動作,因而這個命令可以用來把抽出的塊放置在新行上。暫存器也可以是 '=',跟隨一個可選的表示式。表示式繼續到該命令結束為止。你需要在 '|' 和 '"' 字元前加上反斜槓不讓它們終止你的命令列。例如: :put ='path' . \",/test\" ;如果 '=' 之後沒有表示式,Vim 使用前一個表示式。用 ":dis =" 你可以看到它。|
示例四
用法: 將所有匹配行附加到檔案尾
:g/pattern/t$
關於t
的用法,可以輸入help :t
。 它的用法同copy
command | usage |
---|---|
:[line]pu[t]! [x] | 放置文字 [從暫存器 x] 在行號 [line] (預設為當前行) 之前。 |
:[range]co[py] {address} | 把 [range] 指定的行復制到 {address} 給出的行之下。 |
:[range]m[ove] {address} | 把 [range] 指定的行移動到 {address} 給出的行之下。 |
示例五
用法: 將所有匹配行移動到檔案尾
:g/pattern/m$
示例六
用法: 複製所有匹配行到暫存器'a'
qaq:g/pattern/y A
這裡的命令分成兩部分:
qaq
: 清空暫存器'a'的內容:g/pattern/y A
: y A
是一個Ex命令,可以通過help :yank
來了解具體作用,它把所有的匹配行復制(附加)到暫存器'a'中。
:[range]y[ank] [x]
抽出 [range] 所指定的行 [到暫存器 x]。僅當包含|+clipboard| 特性時才可以抽出到 "* 或 "+ 暫存器。
:[range]y[ank] [x] {count}
從 [range] 的最後一行開始 (預設: 當前行|cmdline-ranges|) 抽出 {count} 行 [到暫存器 x]。
示例七
用法: 從本行到行尾將行首的數字都加1
:.,$g/^\d\+/exe "normal! \<C-A>"
.,$
: 從本行到行尾^\d\+
: 行首是數字exe "normal! \<C-A>
: 執行normal命令, 相當於在匹配項上按鍵<C-A>, <C-A>可以將當前數字加1
關於特殊字元,可以輸入help expr-quote
來檢視
s
"string" 字串常數 expr-quote
注意 使用的是雙引號。
字串常數接受以下特殊字元:
字元 | 含義 |
---|---|
\... | 三位八進位制數 (例如,"\316") |
\.. | 兩位八進位制數 (必須後跟非數字) |
\. | 一位八進位制數 (必須後跟非數字) |
\x.. | 兩位十六進位制數指定的位元組 (例如,"\x1f") |
\x. | 一位十六進位制數指定的位元組 (必須後跟非十六進位制數字) |
\X.. | 等同於 \x.. |
\X. | 等同於 \x. |
\u.... | 四位十六進位制指定的字元。根據 'encoding' 的當前值決定的編碼進行存貯 (例如,"\u02a4") |
\U.... | 等同於 \u 但接受多達 8 位十六進位制數。 |
\b | 退格 <BS> |
\e | escape <Esc> |
\f | 換頁 <FF> |
\n | 換行 <NL> |
\r | 回車 <CR> |
\t | 製表 <Tab> |
\\ | 反斜槓 |
\" | 雙引號 |
\<xxx> | "xxx" 命名的特殊字元,例如 "\<C-W>" 代表 CTRL-W。用於對映,0x80 位元組被轉義。 |
雙引號必須轉義: "<M-\">"
。
不要用 <Char-xxxx>
來得到 utf-8 字元,用上面提到的 \uxxxxx
。
注意 "\xff" 儲存為位元組 255,在某些編碼中它是不合法的。使用 "\u00ff" 可以按照 'encoding' 的當前值儲存字元 255。
注意 "\000" 和 "\x00" 強制字串結束。
關於遞增和遞減, 可以用help CTRL-A
來檢視
遞 增 與 遞 減 ~CTRL-A
把當前游標之上或之後的數值或者字母加上 [count]。
{Visual}CTRL-A
給高亮文字內的數值或者字母加上 [count]。
{Visual}g CTRL-A
給高亮文字內的數值或者字母加上 [count]。如果高亮超過一 行,每行會加上額外的 [count] (即生成 [count] 為增量的 遞增數列)。
例如,假定有如下數字的列表:
1.
1.
1.
1.
移動至第二個 "1.",可視地選擇後三行,按 g CTRL-A 會生
生成:
1.
2.
3.
4.
CTRL-X
把當前游標之上或之後的數值或者字母減去 [count]。
{Visual}CTRL-X
給高亮文字內的數值或者字母減去 [count]。
MS-Windows 上,此鍵被對映到剪下可視文字 |dos-standard-mappings|。要遮蔽該對映,可用: silent! vunmap <C-X>
{Visual}g CTRL-X
給高亮文字內的數值或者字母減去 [count]。如果高亮超過一 行,每行會減去額外的 [count] (即生成 [count] 為增量的 遞減數列)。
CTRL-A 和 CTRL-X 命令可用於:
- 帶符號或無符號十進位制數
- 無符號二進位制、八進位制和十六進位制數
- 字母
示例八
用途: 在所有包含DEBUG的行用/ ... /變成註釋
" using :normal
g/^\s*DEBUG/exe "norm! I/* \<Esc>A */\<Esc>"
" using :substituting
g/^\s*DEBUG/s!.*!/* & */!
這裡&
用來表示前面的整個匹配項
示例九
用途: 顯示匹配行的上一行
:g/pattern/?^\w?p "if only name is interesting
:g/pattern/ka|?^\w?p|'ap "if name and the lookup-line is interesting
:g/pattern/?^\w?|+,/^[^ ]/-1p "if entire record is interesting
關於?^\w?, 兩個
?之間的就是要匹配的模式,
^\w表示開頭不為空的行,
p表示
put`在前面已經講過?
可以檢視help cmdline-range
.
符號 | 行號 |
---|---|
{number} | 行號 |
. | 當前行 |
$ | 檔案的最後一行 |
% | 相當於 1,$ (整個檔案) |
't | 標記 t 的位置 (小寫) |
'T | 標記 T 的位置 (大寫);如果標記存在於另一個檔案中,則不能在範圍裡應用。 |
/{pattern}[/] | 下一個 匹配 {pattern} 的行 |
?{pattern}[?] | 前一個 匹配 {pattern} 的行 |
/ | 下一個 與前次搜尋模式匹配的行 |
? | 前一個 與前次搜尋模式匹配的行 |
\& | 下一個 與前次替代模式匹配的行 |
關於ka
, 可以檢視help :k
:[range]ma[rk] {a-zA-Z'}
把位置標記 {a-zA-Z'} 設在 [range] 的最後一行,第 0 列。預設的 [range] 是當前行。
:[range]k{a-zA-Z'}
和 :mark 相同, 但是標記名之前的空格可以省略。
示例十
用途: 反轉檔案行
:g/^/m0
前面已經講過m
表示move
示例十一
用途: 在以某關鍵字開關的行尾加上某字元
:g/^pattern/s/$/mytext
示例十二
用途: 刪除匹配行
:g/pattern/d _
預設情況下, 所有刪除行會被複制到unnamed register,當檔案很多時,效能會被影響到,所以這裡把內容複製到黑洞register, 相當於NOP
, 這樣可以提高效能
一些常見命令:
:2,8co15 "copy lines 2 through 8 after line 15
:4,15t$ "copy lines 4 through 15 to end of document (t == co)
:-t$ "copy previous line to end of document
:m0 "move current line to line 0 (i.e. the top of the document)
:.,+3m$-1 "current line through current+3 are moved to the lastLine-1 (i.e. next to last)
示例十三
用途: 在一段範圍裡替換字元
:'a,'bg/pattern/s/pattern2/string/gi
示例十四
用途: 在匹配行,執行暫存器q裡的動作
:g/pattern/normal @q
示例十五
用途: 刪除連續的重複行
:g/^\(.*\)\(\r\?\n\1\)\+$/d
:%!uniq
\r\?\n
可以用於匹配換行, \r
是可選的
當g
用來搜尋多行匹配時,它只將command作用於匹配的第一行, 而不是整個的匹配
示例十六
用途: 合併多個連線的空行為一行
:v/./,/./-j
j
是join
的綜合,它會把多行連線成一行。,/./-
是一個範圍, 完整形式是.,/./-1
, 表示當前行到非空行的上一行
J
連線 [count] 行,但至少包含兩行。刪除縮排,插入不多於兩個的空格 (見下)。在緩衝區末行此操作會失敗。[count] 如果過多,會自行縮減至餘下可用的行。
{Visual}J
連線高亮行,但至少包含兩行。刪除縮排,插入不多於兩個的空格 (見下)。
gJ
連線 [count] 行,但至少包含兩行。不插入或刪除任何空格。
{Visual}gJ
連線高亮行,但至少包含兩行。不插入或刪除任何空格。
[range]j[oin][!] [flags]
連線 [range] 範圍的行。和 "J" 相同,但如有 [!] 時,連線不插入或刪除任何空格。如果 [range] 包括相同的開始和結束行,該命令不做任何事。預設行為是連線當前行與下一行。[flags] 部分可參見 |ex-flags|。
:[range]j[oin][!] {count} [flags]
連線 [range] 開始的 {count} 行 (預設: 當前行 |cmdline-ranges|)。和 "J" 相同,但如有 [!] 時,連線不插入或刪除任何空格。[flags] 部分可參見 |ex-flags|。
示例十七
用途: 對關鍵字包圍的埠宣告按字母排序
:g/\/\/define begin/+1,/\/\/define end/-1 sort:g/{/ .+1,/}/-1 sort
示例十八
用途: 在以"module"開頭的行下面都增加分隔線
:g/^module/t.|s/./\//g
示例十九
用途: 將某字元行下的第二行列印到某個已存在檔案
:g/^Chapter/+2w >> context
引用:
https://vim.fandom.com/wiki/P...
https://wsdjeg.spacevim.org/v...