Linux sed命令的使用方法
了解 sed 的基本用法,然后下载我们的备忘单,以快速参考 Linux 流编辑器。
很少有 Unix 命令能像 sed、grep 和 awk 这样出名。它们经常被聚集在一起,可能是因为它们有奇怪的名字和强大的文本解析工具。它们在语法和逻辑上也有一些相似之处。虽然它们对于解析文本都很有用,但每个都有其特点。本文研究 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,您都可能想尝试一下。如果您在 ports 树中找不到 GNU sed(在非 Linux 系统上通常称为 gsed),那么您可以从 GNU 网站下载其源代码。安装 GNU sed 的好处是,您可以使用它的额外功能,但如果您需要可移植性,还可以限制它符合 sed 的 POSIX 规范。
MacOS 用户可以在 MacPorts 或 Homebrew 上找到 GNU sed。
在 Windows 上,您可以使用 Chocolatey 安装 GNU sed。
理解模式空间和保持空间
sed 一次只处理一行。因为它没有视觉显示,所以它创建一个模式空间,即内存中包含输入流中的当前行的空间(删除任何尾随换行符)。一旦填充了模式空间,sed 就会执行您的指令。当到达命令末尾时,sed 将模式空间的内容打印到输出流。默认输出流是 stdout,但可以使用 --in-place=.bak
选项将输出重定向到文件,甚至返回到同一文件。
然后循环再次从下一个输入行开始。
为了在使用 sed 清理文件时提供一点灵活性,sed 还提供了一个保留空间(有时也称为保留缓冲区),这是 sed 内存中为临时保留的空间。数据存储。您可以将保留空间视为剪贴板,事实上,这正是本文演示的内容:如何使用 sed 进行复制/剪切和粘贴。
首先,创建一个示例文本文件,并将此文本作为其内容:
Line one
Line three
Line two
将数据复制到保留空间
要将某些内容放入 sed 的保留空间,请使用 h
或 H
命令。小写的 h
告诉 sed 覆盖保留空间的当前内容,而大写的 H
告诉 sed 将数据附加到保留空间中已有的内容。
单独使用时,没有什么可看的:
$ sed --quiet -e '/three/ h' example.txt
$
--quiet
(简称 -n
)选项抑制所有输出,但 sed 已根据我的搜索要求执行的操作。在这种情况下,sed 选择任何包含字符串 two
的行,并将其复制到保留空间。我没有告诉 sed 打印任何内容,因此不会产生任何输出。
从保留空间复制数据
要深入了解保留空间,您可以使用 g
命令从保留空间复制其内容并将其放入模式空间。观察会发生什么:
$ sed -n -e '/three/h' -e 'g;p' example.txt
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
)和空保持空间的内容。接下来的两行与搜索文本 (三
) 匹配,因此它包含模式空间和保留空间。第三对行的保留空间不会改变,因此模式空间(第二行
)打印时保留空间(仍然是第三行
)在末尾尾随。
使用 sed 进行剪切和粘贴
现在您已经知道如何在模式和保留空间之间切换字符串,您可以设计一个 sed 脚本来复制、删除和粘贴文档中的一行。例如,本文的示例文件的第三行
顺序不正确。 Sed 可以解决这个问题:
$ sed -n -e '/three/ h' -e '/three/ d' \
-e '/two/ G;p' example.txt
Line one
Line two
Line three
- 第一个脚本找到包含字符串
two
的行,并将其从模式空间复制到保留空间,替换当前保留空间中的任何内容。 - 第二个脚本删除任何包含字符串
two
的行。这相当于在文字处理器或文本编辑器中完成剪切操作。 - 最终脚本找到包含
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!