5.4. 寻址的全局视角

未匹配的标注

5.4 寻址的全局视角

关于 sed 命令,你将首先注意到一点 sed 会将它们应用于每一个输入行。 sed 是隐式全局的,不像 ed, ex 或者 vi。下面的替换命令将每一个 "CA" 替换为 "California"。

s/CA/California/g

如果同样的命令在 vi 里面从 ex 命令提示符键入,那么它就会只替换当前行上的所有匹配。

在 sed 里面,好像每一行都轮流成为当前行,所以命令被应用于每一行。行地址被用来提供一个操作的上下文或限制。(简而言之,在 vi 里面,除非你告诉它要作用于哪一行,否则它什么都不会做。而在 sed 里面它将作用于每一行,除非你告诉它不要去那样做。比如通过向前面那个替换命令提供地址 "Sebastopol",我们能将 "CA" 替换为 "California" 限制在包含 "Sebastopol" 的行。

/Sebastopol/s/CA/California/g

包含 "Sebastopol, CA" 的行将会匹配这个地址,然后替换命令将被应用,将这行改变为 "Sebastopol, California"。包含 "San Francisco, CA" 的行将不会被匹配,替换也不会被应用。

一个 sed 命令能指定 0, 1 或 2 个地址。地址可以是一个描述模式的正则表达式一个行号或者一个行寻址符号。

  • 如果没有地址被指定,那么这个命令就应用于每一行。
  • 如果只有一个地址,这个地址就应用于匹配这个地址的任何行。
  • 如果有两个,分隔的地址被指定,这个命令就从匹配第一个地址的行开始,一直到匹配第二个地址的那一行(包含),在这个范围上执行这个命令。
  • 如果一个地址跟随一个叹号,这个命令就被应用在不匹配这个地址的所有行上。

为了显示地址寻址是如何工作的,让我们用删除命令 d 来看一下例子。一个只包含 d 命令而不包含地址的脚本会没有输出,因为它删除了所有的行:

d

当一个行号被作为地址时,这个命令只影响那一行。比如下面这个命令只删除第一行:

1d

行号,指的是一个被 sed 维护的内部行计数。这个计数器对多个输入文件不会重置。因此不管有多少个文件被指定为输入,在输入流中只有一个 line 1。

类似的输入流只有一个最后一行,它可以用寻址符号 $ 来指定。下面这个例子删除了输入的最后一行:

$d

$ 符号不应该和正则表达式里面的 $ 混淆。那个 $ 意味着是行的末尾。

当一个正则表达式被作为地址,这个命令只影响匹配那个模式的行。这个正则表达式必须用斜杠来包裹。下面这个删除命令:

/^$/d

只删除空行,所有的其它行都原封不动保留下来。

如果你提供两个地址,那么你就指定了一个命令执行的行范围。下面这个命令就显示了如何删除所有被一对宏包裹的行。在这个例子里面,.TS 和 te 就表示 tbl 输入:

/ˆ\.TS/,/ˆ\.TE/d

它删除了匹配第一个模式的行及其之后所有行,一直到匹配第二个模式的行(包含这一行),在这个范围之外的行不会被影响。下面这个命令就删除了文件中第 50 行到最后一行:

50,$d

你可以将行地址和模式地址混在一起。

1,/^$/d

这个例子删除了从第一行一直到第一个空白行的所有行,比如将删除一个你存在一个文件中的 internet 信息的邮件头。

你可以认为第一个地址是启动这个动作。第二个地址是禁用它。没有办法提前决定第二个匹配是否成功。一旦第一个匹配成功,这个动作将应用于所有随后的行,直到第二个匹配成功。在之前的例子中,如果这个文件不包含一个空白行,那么所有的行都会被删除。

一个跟着地址的叹号叹号(!)反转了匹配的含义。比如下面这个脚本删除了所有行除了那些在 tbl 输入里面的。

/ˆ\.TS/,/ˆ\.TE/!d

这个脚本实际上将 tbl 输入从一个源文件中提取出来。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~