1. 全局命令

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

在本章中,您将学习如何在全局命令中重复命令行命令。运行一次,应用于任何地方(在缓冲区中)。

2. 全局命令概述

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

顺便说一句,您之前可能已经听说过“ Ex命令”一词。在本书中,我将它们称为命令行命令,但Ex命令和命令行命令是相同的。它们是以冒号(:)开头的命令。在上一章中,您了解了替代命令。这是一个Ex命令的示例。它们之所以称为Ex,是因为它们最初来自Ex文本编辑器。在本书中,我将继续将它们称为命令行命令。有关Ex命令的完整列表,请查看:h ex-cmd-index

全局命令具有以下语法:

: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);

要删除所有包含“控制台”的行,可以运行:

:g/console/d

结果:

const one = 1;

const two = 2;

const three = 3;

全局命令在与“控制台”模式匹配的所有行上执行删除命令(d)。

运行g命令时,Vim对文件进行两次扫描。在第一次运行时,它将扫描每行并标记与/console/模式匹配的行。一旦所有匹配的行都被标记,它将进行第二次运行,并在标记的行上执行d命令。

如果要删除所有包含“const”的行,请运行:

:g/const/d

结果:

console.log("one: ", one);

console.log("two: ", two);

console.log("three: ", three);

3. 逆向比赛

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

:g!/{pattern}/{command}

要么

:v/{pattern}/{command}

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

4. 模式

全局命令使用与替代命令相同的模式系统,因此本节将作为更新。随意跳到下一部分或继续阅读!

如果您具有以下表达式:

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

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

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

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

:g/one\|two/d

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

:g/[0-9]/d

要么

:g/\d/d

如果您有表达式:

const oneMillion = 1000000;
const oneThousand = 1000;
const one = 1;

要匹配包含三到六个零的行,请运行:

:g/0\{3,6\}/d

5. 传递范围

您可以在g命令之前传递一个范围。您可以通过以下几种方法来做到这一点:

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

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

  • . 表示当前行。范围.,3表示当前行和第3行之间。
  • $ 表示文件的最后一行。 3,$范围表示在第3行和最后一行之间。
  • +n 表示当前行之后的n行。您可以将其与.结合使用,也可以不结合使用。 3,+13,.+1表示在第3行和当前行之后的行之间。

如果您不给它任何范围,默认情况下它将影响整个文件。这实际上不是常态。如果您不传递任何范围,Vim的大多数命令行命令仅在当前行上运行。两个值得注意的例外是全局(:g)和save(:w)命令。

6. 普通命令

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

如果您有以下文字:

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

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

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

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

:g/./normal A;

让我们分解一下:

  • :g 是全局命令。
  • /./ 是“非空行”的模式。回想一下正则表达式中的点(.)表示任何字符。它将行与至少一个字符匹配,因此将行与“const”和“console”匹配。它不匹配空行。
  • normal A; 运行:normal命令行命令。 A; 是普通模式命令,用于在该行的末尾插入";"。

7. 执行宏

您也可以使用全局命令执行宏。宏只是普通模式下的操作,因此可以使用:normal来执行宏。如果您有以下表达式:

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

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

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

请注意,带有"const"的行没有分号。让我们创建一个宏,以在寄存器"a"的这些行的末尾添加逗号:

qa0A;<esc>q

如果您需要复习,请查看有关宏的章节。现在运行:

:g/const/normal @a

现在,所有带有"const"的行都将带有";"在末尾。

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

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

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

8. 递归全局命令

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

给定表达式:

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

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

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

如果您运行:

:g/console/g/two/d

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

您也可以将“g”与“v”结合使用以找到正负模式。例如:

:g/console/v/two/d

而不是查找包含模式"two"的行,它将查找包含"two"的行。

9. 更改定界符

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

要删除包含"console"的行:

:g@console@d

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

g@one@s+const+let+g

此处,全局命令将查找包含“one”的所有行。 替换命令将从这些匹配项中将字符串"const"替换为"let"。

10. 默认命令

如果在全局命令中未指定任何命令行命令,会发生什么?

全局命令将使用打印(:p)命令来打印当前行的文本。如果您运行:

:g/console

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

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

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

它拼写"grep",与命令行中的grep 相同。但这 是巧合。 g/re/p命令最初来自第一行文本编辑器之一的Ed编辑器。 grep命令的名称来自Ed。

您的计算机可能仍具有Ed编辑器。从终端运行ed(提示:要退出,请键入q)。

11. 更多示例

11.1. 反转整个缓冲区

要撤消整个文件,请运行:

:g/^/m 0

^是“行的开始”的模式。使用^匹配所有行,包括空行。

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

:5,10g/^/m 0

要了解有关move命令的更多信息,请查看:h :move

11.2. 汇总所有待办事项

当我编码时,有时我会想到一个随机的绝妙主意。不想失去专注,我通常将它们写在我正在编辑的文件中,例如:

const one = 1;
console.log("one: ", one);
// TODO: feed the puppy

const two = 2;
// TODO:自动喂小狗
console.log("two: ", two);
const three = 3;
console.log("three: ", three);
// TODO:创建一家销售自动小狗喂食器的初创公司

跟踪所有已创建的TODO可能很困难。 Vim有一个:t(copy)方法来将所有匹配项复制到一个地址。要了解有关复制方法的更多信息,请查看:h :copy

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

:g/TODO/t $

结果:

const one = 1;
console.log("one: ", one);
// TODO:喂小狗

const two = 2;
// TODO:自动喂小狗
console.log("two: ", two);

const three = 3;
console.log("three: ", three);
// TODO:创建一家销售自动小狗喂食器的初创公司

// TODO:喂小狗
// TODO:自动喂小狗
// TODO:创建一家销售自动小狗喂食器的初创公司

现在,我可以查看我创建的所有TODO,找到时间来完成它们或将它们委托给其他人,然后继续执行下一个任务。

另一种选择是使用m

:g/TODO/m $

结果:

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

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

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

// TODO:喂小狗
// TODO:自动喂小狗
// TODO:创建一家销售自动小狗喂食器的初创公司

一旦决定要删除列表,就可以删除它。

11.3. 黑洞删除

从寄存器一章回想一下,已删除的文本存储在已编号的寄存器中(允许它们足够大)。每当运行:g/console/d时,Vim都会将删除的行存储在编号寄存器中。如果删除许多行,则可以快速填充所有编号的寄存器。为了避免这种情况,您始终可以使用黑洞寄存器(“ _将删除的行存储到寄存器中。

:g/console/d _

通过在d之后传递_,Vim不会将删除的行保存到任何寄存器中。

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

如果您的文件带有多个空行,如下所示:

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


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





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

您可以快速将每条长长的空行减少为一条空行。运行:

:g/^$/,/./-1j

结果:

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

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

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

让我们分解一下:

  • :g 是全局命令
  • /^$/ 是空行的模式。回想一下,^表示行的开始,$表示行的结束。 ^ $匹配一个空行(一个零字符长的行)。
  • ,/./-1j命令的范围。由于您没有传递起始范围的值,因此它从当前行开始。您之前已经了解到/./是非空行的模式。 ,/./是从当前行到下一个非空行的范围。全局命令的范围/^$/会将您带到console.log("one: ", one);下面的第一行。这是当前行。 /./ 匹配第一条非空行,即const two = 2;行。最后,-1将其偏移一行。第一次匹配的有效范围是console.log("one: ", one);下方的空行和const two = 2;上方的空行。
  • j 是连接命令:j。您可以加入所有作为其范围的行。例如,:1,5j连接第一到第五行。 请注意,您正在j命令之前传递范围(,/./-1)。仅仅因为您在全局命令中使用了命令行命令,并不意味着您不能给它一个范围。在这段代码中,您将传递给j命令自己的范围来执行。您可以在执行全局命令时将范围传递给任何命令。

顺便说一句,如果您想将多条空行减少为无行,而不是将,/./-1 用作j命令的范围,只需使用,/./作为范围:

:g/^$/,/./j

或更简单:

:g/^$/-j

您的文字现在减少为:

const one = 1;
console.log("one: ", one);
const two = 2;
console.log("two: ", two);
const three = 3;
console.log("three: ", three);

11.5. 高级排序

Vim有一个:sort命令来对一个范围内的行进行排序。例如:

d
b
a
e
c

您可以通过运行:sort对它们进行排序。如果给它一个范围,它将只对该范围内的行进行排序。例如,:3,5sort仅在第三和第五行之间排序。

如果您具有以下表达式:

const arrayB = [
  "i",
  "g",
  "h",
  "b",
  "f",
  "d",
  "e",
  "c",
  "a",
]

const arrayA = [
  "h",
  "b",
  "f",
  "d",
  "e",
  "a",
  "c",
]

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

:g/\[/+1,/\]/-1sort

结果:

const arrayB = [
  "a",
  "b",
  "c",
  "d",
  "e",
  "f",
  "g",
  "h",
  "i",
]

const arrayA = [
  "a"
  "b",
  "c",
  "d",
  "e",
  "f",
  "h",
]

这很棒!但是命令看起来很复杂。让我们分解一下。该命令包含三个主要部分:全局命令模式,排序命令范围和排序命令。

:g/\[/ 是全局命令模式。

  • :g 是全局命令。
  • /\[/ 是全局命令使用的模式。 \[查找文字"["字符串。

+1,/\]/-1 是排序命令的范围。

  • 范围可以有开始和结束地址。在这种情况下,+1是起始地址,/\]/-1是结束地址。
  • +1 表示当前行之后的行,这是与全局命令中的模式“ [”匹配的行。 “ +1”将当前行偏移一行。因此,在第一个匹配项中,范围实际上是在const arrayB = [文本之后的一行。
  • /\]/-1 是结束地址。 \]代表一个文字的右方括号“]”。 -1将其偏移一行。结束地址是"]"上方的行。

sort是sort命令行命令。它对给定范围内的所有内容进行排序。 "["到上方的行"]"之后的所有内容均已排序。

如果您仍然对该命令感到困惑,请不要担心。我花了很长时间才掌握它。稍事休息,离开屏幕,然后重新思考。

12. 聪明地学习全局命令

全局命令针对所有匹配的行执行命令行命令。有了它,您只需要运行一次命令,Vim就会为您完成其余的工作。要精通全局命令,需要做两件事:良好的命令行命令词汇表和正则表达式知识。随着您花费更多的时间使用Vim,您自然会学到更多的命令行命令。正则表达式知识将需要更积极的方法。但是,一旦您对正则表达式感到满意,您将领先于很多。

这里的一些例子很复杂。不要被吓到。真是花时间了解它们。学习阅读模式。确保您知道每个命令中的每个字母代表什么。不要放弃。

每当需要在多个位置应用命令时,请暂停并查看是否可以使用g命令。寻找最适合工作的命令,并编写一个模式以同时定位多个目标。然后重复执行此操作,直到您无需考虑即可进行操作。下次,看看是否有更快,更有效的方法。

既然您已经知道全局命令的功能强大,那么让我们学习如何使用外部命令来增加工具库。

Copyright © Kilvn 2021. all right reserved,powered by Gitbook最后更新时间: 2021-10-12 17:14:24

results matching ""

    No results matching ""