vim之強大的global

harriszh發表於2022-04-29

vim global

:global 命令是 Vim 中一個更強大的命令 (之一)。它允許你找到一個匹配點並且在那裡執行一個命令。它的一般形式是:

:[range]g/{pattern}/{command}

在每一匹配行上執行命令command. 這個命令只能是冒號命令, 普通模式命令不能在這裡使用。如果需要,可以使用:normal命令。

如果要檢視可以使用的命令,可以help ex-cmd-index。 如果要檢視詳細解釋, 檢視help 10.4help multi-repeat

vglobal相當於global!, 兩者可以組合使用, 如:g/found/v/notfound/{cmd}

利用global我們可以把我們之前學的很多東西都串連起來,以完全一些非常奇妙的動作。

所以下面我們通過示例來學習global的用法。

示例

示例一

用法: 顯示匹配行上下共3行, 第二寫法能更清晰的看到上下3行

:g/patttern/z#.3
:g/pattern/z#.3|echo "========"

圖片.png

關於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

commandusage
:[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>
\eescape <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
  • jjoin的綜合,它會把多行連線成一行。
  • ,/./-是一個範圍, 完整形式是.,/./-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

圖片.png

示例十八

用途: 在以"module"開頭的行下面都增加分隔線

:g/^module/t.|s/./\//g

圖片.png

示例十九

用途: 將某字元行下的第二行列印到某個已存在檔案

:g/^Chapter/+2w >> context

圖片.png

引用:
https://vim.fandom.com/wiki/P...
https://wsdjeg.spacevim.org/v...

相關文章