Learn Vim 第十三章:全局命令

本文翻译自 iggredible/Learn-Vim,部分内容有增改。

到目前为止,您已经了解了如何使用点命令(.)重复上一次更改,如何使用宏(q)重复动作以及将文本存储在寄存器中(")。

在本章中,您将学习如何在全局命令中重复命令行命令。

全局命令概述

Vim的全局命令用于同时在多行上运行命令行命令。

全局命令具有以下语法:

:g/pattern/command

pattern匹配包含该模式串的所有行,类似于替代命令中的模式串。command可以是任何命令行命令。全局命令通过对与pattern匹配的每一行执行command来工作。

如果您具有以下表达式:

const one = 1;
console.log("one: ", one);

const two = 2;
console.log("two: ", two);

const three = 3;
console.log("three: ", three);

要删除所有包含”console”的行,可以运行:

:g/console/d

结果:

const one = 1;

const two = 2;

const three = 3;

全局命令在与”console”模式串匹配的所有行上执行删除命令(d)。

逆向匹配

要在不匹配的行上运行全局命令,可以运行:

:g!/{pattern}/{command}

或者

:v/{pattern}/{command}

如果运行:v/console/d,它将删除 不 包含”console”的所有行。

模式串

全局命令使用与替代命令相同的模式串系统。

要删除包含”one”或”two”的行,请运行:

:g/one\|two/d

要删除包含任何一位数字的行,请运行:

:g/\d/d

传递范围参数

您可以在g命令之前传递一个范围:

  • :1,5g/console/d 删除第1行和第5行之间匹配字符串”console”的行。
  • :,5g/console/d 如果逗号前没有地址,则从当前行开始。
  • :3,g/console/d 如果逗号后没有地址,则在当前行结束。
  • :3g/console/d 如果只传递一个地址而不带逗号,则仅在第3行执行命令。

除了数字,您还可以将这些符号用作范围:

  • . 表示当前行。
  • $ 表示文件的最后一行。
  • +n 表示当前行之后的n行。

普通模式命令

您可以将全局命令和:normal命令行命令一起运行。

如果您有以下文字:

const one = 1
console.log("one: ", one)

const two = 2
console.log("two: ", two)

要添加”;”运行到每一行的末尾:

:g/./normal A;
  • :g 是全局命令。
  • /./ 是”非空行”的模式。它匹配至少包含1个字符的行。
  • normal A; 运行:normal命令行命令。 A; 是普通模式命令,用于在该行的末尾插入”;”。

执行宏

您也可以使用全局命令执行宏。如果您有以下表达式:

const one = 1
console.log("one: ", one);

const two = 2
console.log("two: ", two);

创建一个宏,以在寄存器”a”的这些行的末尾添加分号:

qa0A;<esc>q

现在运行:

:g/const/normal @a

所有带有”const”的行的末尾将带有”;”。

递归全局命令

全局命令本身是命令行命令的一种,因此您可以从技术上在全局命令中运行全局命令。

:g/console/g/two/d

首先,g将查找包含模式”console”的行。然后,第二个”g”将从那三个匹配项中查找包含模式”two”的行。最后,它将删除该匹配项。

您也可以将g与v结合使用以找到正负模式:

:g/console/v/two/d

它将查找 不 包含”two”的行。

更改定界符

您可以像替代命令一样更改全局命令的定界符。规则是相同的:您可以使用任何单字节字符,但字母,数字,", |, 和 \除外。

要删除包含”console”的行:

:g@console@d

如果在全局命令中使用替代命令,则可以有两个不同的定界符:

g@one@s+const+let+g

默认命令

如果在全局命令中未指定任何命令行命令,全局命令将使用打印(:p)命令来打印当前行的文本。

:g/console

它将在屏幕底部打印所有包含”console”的行。

顺便说一句,这是一个有趣的事实。因为全局命令使用的默认命令是p,所以这使g语法为:

:g/re/p
  • g = 全局命令
  • re = 正则表达式模式
  • p = 打印命令

这三个元素连起来拼写为 “grep”,与命令行中的grep 相同。g/re/p命令最初来自Ed编辑器。

反转整个缓冲区

要翻转整个文件,请运行:

:g/^/m 0 

如果只需要反转几行,请将其传递一个范围。要将第5行到第10行之间的行反转,请运行:

:5,10g/^/m 0

汇总所有待办事项

要将所有TODO复制到文件末尾以便于自省,请运行:

:g/TODO/t $

如果不想复制,而是将所有的 TODO 移动到末尾,可以使用移动命令 m:

:g/TODO/m $

黑洞删除

为了避免删除的行存储到寄存器中,您可以使用黑洞寄存器("_):

:g/console/d _

将多条空行减少为一条空行

:g/^$/,/./-1j
  • /^$/ 表示一个空行。
  • /./ 表示一个非空行。-1 意思是向上偏移1行。
  • j 是联接命令。

如果想要将多个空行全部删去:

:g/^$/,/./j

高级排序

如果需要排序数组中的元素,而不是数组本身,可以运行以下命令:

:g/\[/+1,/\]/-1sort
  • /\[/+1 匹配左方括号”[“的下面1行。
  • /\]/-1 匹配右方括号”]”的上面1行。
  • sort 是命令行命令:排序。

聪明地学习全局命令

全局命令针对所有匹配的行执行命令行命令。有了它,您只需要运行一次命令,Vim就会为您完成其余的工作。要精通全局命令,需要做两件事:良好的命令行命令词汇表和正则表达式知识。

每当需要在多个位置应用命令时,请暂停并查看是否可以使用g命令。寻找最适合工作的命令,并编写一个模式串以同时定位多个目标。