如何使用 Linux sed 命令

学习 sed 的基本用法,然后下载我们的速查表,以便快速参考 Linux 流编辑器。
67 位读者喜欢这个。
How Linux became my job

Opensource.com

很少有 Unix 命令像 sed、grepawk 这样出名。它们经常被归为一类,可能是因为它们有奇怪的名字和强大的文本解析工具。它们也共享一些句法和逻辑上的相似之处。虽然它们都可用于解析文本,但每个都有其专长。本文研究 sed 命令,它是一个流编辑器

我之前写过关于 sed 及其远亲 ed 的文章。为了熟悉 sed,对 ed 有一定的了解会有所帮助,因为这有助于你习惯缓冲区的概念。本文假设你熟悉 sed 的基本知识,这意味着你至少运行过经典的 s/foo/bar/ 风格的查找和替换命令。

[下载我们的免费 sed 速查表]

安装 sed

如果你正在使用 Linux、BSD 或 macOS,你已经安装了 GNU 或 BSD sed。这些是对原始 sed 命令的独特重新实现,虽然它们很相似,但也存在细微差异。本文已在 Linux 和 NetBSD 版本上进行了测试,因此在这种情况下,你可以使用计算机上的任何 sed,但对于 BSD sed,你必须仅使用短选项(例如 -n 而不是 --quiet)。

GNU sed 通常被认为是功能最丰富的 sed,因此无论你是否运行 Linux,你都可能想尝试一下。如果你在端口树中找不到 GNU sed(在非 Linux 系统上通常称为 gsed),那么你可以从 GNU 网站 下载其源代码。安装 GNU sed 的好处是,你可以使用它的额外功能,但也可以约束它以符合 POSIX sed 规范,如果你需要可移植性的话。

MacOS 用户可以在 MacPortsHomebrew 上找到 GNU sed。

在 Windows 上,你可以使用 Chocolatey 安装 GNU sed

理解模式空间和保持空间

Sed 一次只处理一行。因为它没有可视化显示,所以它创建了一个模式空间,这是内存中的一个空间,包含来自输入流的当前行(删除了任何尾随换行符)。一旦你填充了模式空间,sed 就会执行你的指令。当它到达命令末尾时,sed 会将模式空间的内容打印到输出流。默认输出流是 stdout,但输出可以使用 --in-place=.bak 选项重定向到文件,甚至重定向回同一文件。

然后循环再次从下一输入行开始。

为了在你使用 sed 浏览文件时提供一点灵活性,sed 还提供了一个保持空间(有时也称为保持缓冲区),这是 sed 内存中保留用于临时数据存储的空间。你可以将保持空间视为剪贴板,事实上,这正是本文演示的内容:如何使用 sed 复制/剪切和粘贴。

首先,创建一个示例文本文件,内容如下

Line one
Line three
Line two

将数据复制到保持空间

要将内容放入 sed 的保持空间,请使用 hH 命令。小写 h 告诉 sed 覆盖保持空间的当前内容,而大写 H 告诉它将数据追加到保持空间中已有的内容。

单独使用时,没有什么可看的

$ sed --quiet -e '/three/ h' example.txt
$

--quiet 选项(简写为 -n)禁止所有输出,但 sed 为我的搜索要求执行的操作除外。在本例中,sed 选择任何包含字符串 three 的行,并将其复制到保持空间。我没有告诉 sed 打印任何内容,因此不产生输出。

从保持空间复制数据

为了深入了解保持空间,你可以从保持空间复制其内容,并使用 g 命令将其放入模式空间。观察会发生什么

$ sed -n -e '/three/h' -e 'g;p' example.txt

Line three
Line three

第一个空行打印是因为当保持空间第一次复制到模式空间时,它是空的。

接下来的两行包含 Line three,因为这是从第二行开始保持空间中的内容。

此命令使用两个唯一的脚本 (-e) 纯粹是为了帮助提高可读性和组织性。将步骤划分为单独的脚本可能很有用,但从技术上讲,此命令与一个脚本语句的效果相同

$ sed -n -e '/three/h ; g ; p' example.txt

Line three
Line three

将数据追加到模式空间

G 命令将换行符和保持空间的内容追加到模式空间。

$ sed -n -e '/three/h' -e 'G;p' example.txt
Line one

Line three
Line three
Line two
Line three

此输出的前两行包含模式空间 (Line one) 和空保持空间的内容。接下来的两行与搜索文本 (three) 匹配,因此它包含模式空间和保持空间。保持空间对于第三对行没有变化,因此模式空间 (Line two) 与保持空间(仍然是 Line three)一起打印在末尾。

使用 sed 进行剪切和粘贴

现在你已经知道如何将字符串从模式空间来回移动到保持空间,你可以设计一个 sed 脚本,该脚本可以在文档中复制、然后删除、然后粘贴一行。例如,本文的示例文件中的 Line three 顺序错误。Sed 可以修复它

$ sed -n -e '/three/ h' -e '/three/ d' \
-e '/two/ G;p' example.txt
Line one
Line two
Line three
  • 第一个脚本查找包含字符串 three 的行,并将其从模式空间复制到保持空间,替换当前保持空间中的任何内容。
  • 第二个脚本删除任何包含字符串 three 的行。这完成了相当于文字处理器或文本编辑器中的剪切操作。
  • 最后一个脚本查找包含 two 的行,并将保持空间的内容追加到模式空间,然后打印模式空间。

任务完成。

使用 sed 编写脚本

再次强调,使用单独的脚本语句纯粹是为了视觉和精神上的简洁。剪切和粘贴命令可以作为一个脚本工作

$ sed -n -e '/three/ h ; /three/ d ; /two/ G ; p' example.txt
Line one
Line two
Line three

它甚至可以编写为专用脚本文件

#!/usr/bin/sed -nf

/three/h
/three/d
/two/ G
p

要运行脚本,请将其标记为可执行文件并在你的示例文件上尝试它

$ chmod +x myscript.sed
$ ./myscript.sed example.txt
Line one
Line two
Line three

当然,你需要解析的文本越可预测,就越容易使用 sed 解决你的问题。为 sed 操作(例如复制和粘贴)发明“配方”通常是不切实际的,因为触发操作的条件可能因文件而异。但是,你越流利地使用 sed 命令,就越容易根据你需要解析的输入来设计复杂的操作。

重要的是识别不同的操作,了解 sed 何时移动到下一行,以及预测模式空间和保持空间可能包含的内容。

下载速查表

Sed 很复杂。它只有十几个命令,但其灵活的语法和原始功能意味着它充满了无限的潜力。我过去常常参考几页巧妙的单行代码,试图充分利用 sed,但直到我开始发明(有时是重新发明)自己的解决方案,我才觉得自己开始真正学习 sed。如果你正在寻找关于命令的温和提醒和关于语法的有用提示,下载我们的 sed 速查表,并一劳永逸地开始学习 sed!

接下来阅读什么
标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算机行业工作,而且经常同时工作。

评论已关闭。

© . All rights reserved.