vim 底行命令模式下的全局命令 g(global)
文章目錄
- 命令格式介紹
- 常用的 ex 指令
- 關于 range
- 參考示例
- 結合替換指令 s 使用
- 將包含 pattern 的行追加到指定的寄存器中
- 插入空行
- 打印符合要求的行
- 刪除匹配的行
- 刪除不匹配的行
- 刪除空行
- 刪除大量匹配行
- 移動匹配的行
- 復制匹配的行
- 復制到 register a
- 反轉文件中的每一行
- 在匹配行后添加文字
- 批量文本操作
注:以下命令都是在底行命令模式下執行。
命令格式介紹
全局命令 g 在 Vim 的底行命令模式下有著意想不到強大的功能。當想要在整個文件中對于匹配的行或者非匹配行進行一些操作時,應該第一時間想到這個 g 命令
[range]global[!]/{pattern}/{command}整體解釋:
整個命令可以理解成,在 range 范圍內對匹配或者不匹配 pattern 的行執行 command;用于指示 vim 在 [range] 界定范圍內對(不)匹配模式 {pattern} 的文本行執行 ex 命令 [command]。
分解說明:
| range | 指定文本范圍,不寫則默認為整個文檔(%)。也就是說命令 global 默認的作用范圍是整個文檔 |
| global | global 可以簡寫為 g。其作用就是篩選出包含 pattern 的行 |
| ! | 表示取反,即篩選出不匹配 pattern 的行,在沒有匹配到指定模式的行上執行 command。也可以使用 vglobal、v |
| pattern | 指定要命令 global/ 要匹配的目標模式,如果不填寫,默認使用上一次的查找模式。擴展:寄存器 "/ 保存這上一次的查找模式,可以在底行命令模式下輸入 reg "/ 查看 |
| command | 就是 ex 指令,command 默認是打印文本,也就是說不寫指令,則默認的指令是 p,print 的縮寫,表示打印輸出,即會把所有包含 pattern 的行輸出。詳見《vim 的 ex 指令》 |
注意:
如果不寫 g,則會對 range 整體執行命令,g 是將 command 作用于包含 pattern 的每行。例如,%/liaowenxiong/d,% 表示整個文檔,所以只要文檔中能夠匹配到 liaowenxiong,則整個文檔會被刪除。
常用的 ex 指令
| d | 刪除 |
| m | 移動 |
| t | 拷貝 |
| s | 替換 |
更多的 ex 指令詳見《vim 的 ex 指令》??梢酝ㄟ^在“底行命令模式”下輸入 help command 來查看所有命令的說明文檔。
注:dd、daw 等指令不是 ex 指令,而是 vi 指令。
關于 range
詳見《vim 底行命令模式的正則表達式》中關于 range 的介紹。
參考示例
結合替換指令 s 使用
g/pattern/s/old/new/gcg 的作用就是篩選出包含 pattern 的行,這些行可以執行后面的 s 指令,將 old 替換成 new;后面的 g 表示將行中所以匹配到 old 都替換成功 new,c 表示每次替換都需要用戶的確認。
將包含 pattern 的行追加到指定的寄存器中
g/TODO/yank A將包含 TODO 的行全部復制到寄存器 a中,而且是以“追加”的方式;yank 表示復制,可以縮寫為 y;A 代表寄存器 a,大寫形式表示“追加”,如果小寫則是“覆蓋”。
插入空行
比如在 20 行到 200 行之間,每一行下插入空行:
20,200g/^/pu _g 其實是對行進行篩選,上述命令中,表示從第 20 行到第 200 行之間的文本行中,只有含有 pattern 的行才有資格執行后面的指令(pu _)
注:^ 表示匹配行的頭部;pu 是 ex 指令,是單詞 put 的縮寫,表示粘貼、放置;下劃線 _ 是黑洞寄存器,黑洞寄存器里面啥也沒有,所以 pu _ 就相當于在每行下方插入空行。
可以在底行命令模式下輸入以下命令查看使用說明:
:h :pu關于命令 :pu 的使用說明如下:
:[line]pu[t] [x] Put the text [from register x] after [line] (default current line). This always works linewise, thus this command can be used to put a yanked block as new lines.打印符合要求的行
g/pattern/p打印輸出所有包含模式 pattern 的行,p 是 print
g!/pattern/nu打印輸出所有不包含 pattern 的行的行號,nu 是 number
20, 40g/pattern/p將文檔的第 20 行至第 40 行中包含 pattern 的行打印輸出
刪除匹配的行
刪除與pattern匹配的行
g/pattern/d刪除空白行
g/^$/d刪除不匹配的行
g!/pattern/d v/pattern/d vglobal/pattern/d // 沒有驗證過,不知道行不行 inverse/pattern/d // 沒有驗證過,不知道行不行刪除空行
g/^$/d刪除大量匹配行
Vim 在刪除操作時,會先把要刪除的內容放到寄存器中,假如沒有指定寄存器,會默認放到一個未命名的寄存器中,對于要刪除大量匹配行的行為,可能導致 Vim 花一些時間處理這些拷貝,避免花費不必要的時間可以指定一個 blackhole 寄存器 _
g/pattern/d_移動匹配的行
將所有匹配的行移動到文件的末尾
g/pattern/m$復制匹配的行
將所有匹配的行復制到文件末尾
g/pattern/t$復制到 register a
Vim每個字母都是一個寄存器,所以使用全局命令也可以將內容復制到某一個寄存器,比如 a。
先在普通命令模式下輸入:qaq,清空寄存器 a。
qaqqaq 清空寄存器 a,qa 開始記錄命令到 a 寄存器,q 停止記錄。
然后在底行命令模式下輸入以下的命令:
g/pattern/y Ay 表示復制,大寫英文字母 A 表示把內容追加到寄存器 a 中,所以大寫字母 A 包含兩層含義,其一是指寄存器 a;其二是指 append。所以 y A 表示將匹配到的內容復制到寄存器 a 中。如果使用小寫的 a,則會覆蓋寄存器 a 原有的內容。
存放到 a 寄存器之后就可以使用命令 "ap 來粘貼使用,其中 "a 表示寄存器 a,p 表示粘貼。
反轉文件中的每一行
g/^/m0解釋:
^ 表示行首,每行都有行首,所以相當于匹配到所有的行;m 表示移動;0 表示文檔第 1 行的上方。匹配過程是這樣的,先匹配到文檔的第 1 行,然后移到文檔的最上方;接著匹配到第 2 行,也移動到文檔的最上方,此時文檔的最上方就是第 1 行文本的上方;后面就依照這樣的堆疊順序一行行往上放,最后所有的行就被倒過來了。
在匹配行后添加文字
使用替換命令 s 在每行末尾插入字符串 mytext。
%s/$/mytext同樣使用全局 g 命令也可以實現同樣的效果,很顯然全局 g 命令把問題復雜化了。
g/pattern/s/$/mytextg/pattern/ 匹配到需要在行尾插入字符串的行,再結合替換命令 s 將行尾替換成 mytext,即在行尾插入 mytext
批量文本操作
示例 1,源文本如下:
1.歪曲觀點 我: 我昨天買了個索尼相機誒,挺好用的。 小明:什么?你居然買日貨,你肯定是個看不起國貨想讓我國經濟衰退的讓日本有機可乘的叛徒。 2.錯誤歸因 小明:解放后我國出版社越來越多,人均壽命也不斷提高,所以多開出版社能提高人均壽命。 3.訴諸感情 我在吃紅燒狗肉。小明:你怎么能吃狗肉,狗狗是我們的朋友你居然忍心吃你的朋友? 4.謬誤謬誤(以單個謬誤全盤否定所有觀點) 我:吃肯打雞能增強體質。期望得到的結果是:
# 1.歪曲觀點 我: 我昨天買了個索尼相機誒,挺好用的。 小明:什么?你居然買日貨,你肯定是個看不起國貨想讓我國經濟衰退的讓日本有機可乘的叛徒。# 2.錯誤歸因 小明:解放后我國出版社越來越多,人均壽命也不斷提高,所以多開出版社能提高人均壽命。# 3.訴諸感情 我在吃紅燒狗肉。小明:你怎么能吃狗肉,狗狗是我們的朋友你居然忍心吃你的朋友?# 4.謬誤謬誤(以單個謬誤全盤否定所有觀點) 我:吃肯打雞能增強體質。 小明:胡說,肯打雞是垃圾食品。你個騙子,我再也不要增強體質了。思路:找到數字開頭的文本行,在這些文本上面插入空白行,達到上下隔開的段落效果,接著在這些文本行中插入一個 # 和一個空白字符,即 #
g/^[0-9]/norm O^[ji# ^[| g/^[0-9]/ | 使用 global 命令,得到行首是數字的行 |
| norm | 表示執行普通命令模式的指令,normal 的縮寫 |
| O | 在當前行前面插入一行 |
| ^[ | 退出插入模式,居然可以這樣,實在屌! |
| j | 調入下一行 |
| i | 進入插入模式 |
| “# ” | 插入字符 # 和一個空格 |
示例 2,源文本如下:
對人不對事 當爭論的一方對另一方的觀點本身沒辦法辯論時,往往就會采取攻擊對方本人,而不是觀點本身的方法。所謂的對人不對事,就是 在他人辯論時,通過向公眾傳達關于對手的與論證無關的信息,例如生活中的負面信息,以此來達到擊敗對手的目的。這種謬誤制造者的目的是轉移聽眾對論證的注 意力,這種情形通常是由于論證者本人處于劣勢。 這種“論證”的目的僅僅是獲勝,它可以使聽眾以同論證毫不相關的理由來反對你的對手,而你則可以用同樣的理由來取悅聽眾。造成的后果是,你可以慶祝你戰勝了對手,但恰恰是你所沒有做到的的——至少在邏輯上。你的勝利并非源于觀點的價值,而是源于你擾亂聽眾視聽的能力。 如方韓論戰中,韓寒早期的言論是人身攻擊的急先鋒。他上來就說方舟子禿頭、方的支持者老婆偷人、精子沒有活力,等等,但是問題在于,縱然這些敘述全都為真,方舟子說“韓寒被代筆”仍然有可能是正確的。這樣的邏輯錯誤,正如說司馬遷沒有小雞雞所以寫不出偉大的作品一樣。 又 比如有人說,一個賽車界的天才不可能也是文學天才。這是利用韓寒人生的其他成就來抹殺文學成就的可能性,同樣是一種對人不對事的攻擊。一個人完全可能同時 是賽車天才和文學天才,正如波羅丁既是化學家又是音樂家,羅素則作為數學家獲得了諾貝爾文學獎,對于天才來說,在兩個完全不相干的領域內取得成功絕不是不 可能的。綁架情感 【我愛你,所以你得聽我的】【他在這件事上七分功勞三分錯誤,功過相抵,還是功勞多】 前者是我們社會最典型的一個愛 的謊言,父母們用這個謊言控制孩子,老師們用這個謊言控制學生,男人用這個謊言控制女人,女人也用這個謊言控制男人。對于后者,我們不能因為一個人偉大就 無條件支持。對就是對,錯就是錯,不能用他的功抵他的過,應該一碼歸一碼否則就是和稀泥,什么事情也談不清楚。 綁架情感發生的表現為,故意忽略或 低估手頭上的問題,只是把焦點放在論證的外圍問題,或者無關的問題上,通過這樣來直接影響聽眾的情感,試圖贏得他們的同情。強烈的情感和清晰的思維是成反 比的,一旦情感超過一定界限,引導論證正確進行的機會就隨之歸零。于是,受眾受情感的迷惑放棄了合理辯駁的權利,強詞奪理獲得通行。 像某“韓粉”說的話里,就犯了這樣的錯誤:在具有同等影響力的公眾人物里,只有韓寒愿意討論這個國家和民族的未來,只有他不愿意活得像一個畜生,這就是啟蒙,人不是有名有利就可以滿足的低等動物。就憑這一點,我就支持他,哪怕韓寒最后被證明有代筆的過去,我也支持他。期望得到的結果是:
# 1. 對人不對事 當爭論的一方對另一方的觀點本身沒辦法辯論時,往往就會采取攻擊對方本人,而不是觀點本身的方法。所謂的對人不對事,就是 在他人辯論時,通過向公眾傳達關于對手的與論證無關的信息,例如生活中的負面信息,以此來達到擊敗對手的目的。這種謬誤制造者的目的是轉移聽眾對論證的注 意力,這種情形通常是由于論證者本人處于劣勢。 這種“論證”的目的僅僅是獲勝,它可以使聽眾以同論證毫不相關的理由來反對你的對手,而你則可以用同樣的理由來取悅聽眾。造成的后果是,你可以慶祝你戰勝了對手,但恰恰是你所沒有做到的的——至少在邏輯上。你的勝利并非源于觀點的價值,而是源于你擾亂聽眾視聽的能力。 如方韓論戰中,韓寒早期的言論是人身攻擊的急先鋒。他上來就說方舟子禿頭、方的支持者老婆偷人、精子沒有活力,等等,但是問題在于,縱然這些敘述全都為真,方舟子說“韓寒被代筆”仍然有可能是正確的。這樣的邏輯錯誤,正如說司馬遷沒有小雞雞所以寫不出偉大的作品一樣。 又 比如有人說,一個賽車界的天才不可能也是文學天才。這是利用韓寒人生的其他成就來抹殺文學成就的可能性,同樣是一種對人不對事的攻擊。一個人完全可能同時 是賽車天才和文學天才,正如波羅丁既是化學家又是音樂家,羅素則作為數學家獲得了諾貝爾文學獎,對于天才來說,在兩個完全不相干的領域內取得成功絕不是不 可能的。# 2. 綁架情感 【我愛你,所以你得聽我的】【他在這件事上七分功勞三分錯誤,功過相抵,還是功勞多】 前者是我們社會最典型的一個愛 的謊言,父母們用這個謊言控制孩子,老師們用這個謊言控制學生,男人用這個謊言控制女人,女人也用這個謊言控制男人。對于后者,我們不能因為一個人偉大就 無條件支持。對就是對,錯就是錯,不能用他的功抵他的過,應該一碼歸一碼否則就是和稀泥,什么事情也談不清楚。 綁架情感發生的表現為,故意忽略或 低估手頭上的問題,只是把焦點放在論證的外圍問題,或者無關的問題上,通過這樣來直接影響聽眾的情感,試圖贏得他們的同情。強烈的情感和清晰的思維是成反 比的,一旦情感超過一定界限,引導論證正確進行的機會就隨之歸零。于是,受眾受情感的迷惑放棄了合理辯駁的權利,強詞奪理獲得通行。 像某“韓粉”說的話里,就犯了這樣的錯誤:在具有同等影響力的公眾人物里,只有韓寒愿意討論這個國家和民族的未來,只有他不愿意活得像一個畜生,這就是啟蒙,人不是有名有利就可以滿足的低等動物。就憑這一點,我就支持他,哪怕韓寒最后被證明有代筆的過去,我也支持他。vim 命令如下:
let i=1 | g/.\{2,40}/if(strlen(getline('.'))< 40) | s/^/\='# '.i.'. '/ | let i+=1 | endif| g/.\{2, 40} | 篩查出含有 2-40 個任意字符的文本行,空白行只含有一個空白字符(1 個換行符),所以被排除在外 |
| strlen(getline('.'))< 40 | getline('.') 獲得包含 pattern 的文本行的內容; strlen() 返回字符串的字節數,1 個漢字等于 3 個字節 |
| if(cond1) | command | endif | 如果 cond1== true,執行 command,所以上述命令就是,命令 global 篩查出的文本行的內容的總字節數小于 40,則會執行替換指令,否則什么也不做 |
| let | let 是一個計算指令,所以 let i+=1,就會計算后面的運算表達式,每執行 1 次,變量 i 都會 +1 |
| \='# '.i.'. ' | \= 這是用來拼接字符串和變量的,拼接的變量左右兩邊要加上 .,字符串可以使用單引號或者雙引號包裹起來 |
| | | 豎線 | 是命令的分隔符,用來組合 ex 命令的,具體可以參考《vim 的 ex 指令》 |
總結
以上是生活随笔為你收集整理的vim 底行命令模式下的全局命令 g(global)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的世界怎么设置重生点(我的世界怎么设置
- 下一篇: vim 寄存器中的 ^@,^M,^J