命令 sed 是流编辑器(stream editor)的缩写。它是 Linux/UNIX 系统上非常流行的一个工具。 Sed 本身并不是一个文本编辑器。然而,它可以执行各种修改来操作给定的文本。文本输入是以流的形式发送的。 Sed 然后在流上执行指示的操作。本指南 概述了 sed 命令以及如何操作它,以便在 Linux 中成功操作文本。
Linux 中的 Sed
的输入流 sed 可以来自文本文件或 STDIN(标准输入)。我们可以处理另一个命令的输出,或者直接处理文本文件。 sed 工具预装在所有 Linux 发行版上。
Sed 用法概述
The sed 命令遵循以下结构:
|
1 |
$ sed <选项> <命令> <文件> |
为了演示目的,我们获取了文本版本的 GPL 许可证版本 3:
|
1 |
$ wget https://www.gnu.org/licenses/gpl-3.0.txt |
以下 sed 命令将打印文本文件的内容:
|
1 |
$ sed '' gpl-3.0.txt |
在这里,sed 正在执行单引号中描述的操作并打印输出。由于没有定义选项,sed 将简单地执行空操作并打印文件的全部内容。
Sed 也接受来自其他命令的输出作为输入流。在下一个示例中,将 GPL v3 文本文件的内容通过管道传输到 sed 以执行空操作:
|
1 |
$ cat gpl-3.0.txt | sed '' |
如何打印行
在不给出任何选项的情况下,sed 将直接打印文件的所有内容。相反,我们可以显式发送打印命令,将结果直接打印到标准输出(STDOUT)。
要打印输出,请使用字符 p:
|
1 |
$ sed 'p' gpl-3.0.txt |
默认情况下,sed 将输出打印到屏幕。因为我们特意使用了打印命令,sed 将把每行打印两次。 Sed 是逐行操作的。它读取一行,执行特定操作,将其打印出来,然后移动到下一行。
正如我们所见,每一行都被打印了两次。如果像这样令人困惑,我们可以使用 -n 选项来清理它。它会抑制自动打印功能。因为我们发送了打印命令,所以不需要启用默认的输出打印功能:
|
1 |
$ sed -n 'p' gpl-3.0.txt |
正则表达式字符类
在正则表达式中,有各种字符类。这些类中的每一个都有一个范围。许多类也有多个表达式。大多数类是字符范围:
-
- [a-z]:小写字符
-
- [A-Z]:大写字符
-
- [0-9]:数字
-
- [a-zA-z]:字母
-
- [a-zA-z0-9]:任何字母数字字符
这些字符类也有不同的表示法:
-
- [:lower:]:小写字符
-
- [:upper:]:大写字符
-
- [:digit:]:数字
-
- [:alpha:]:字母
-
- [:alphanum:]:字母数字字符
例如,以下命令将打印包含至少一个数字的所有行:
|
1 |
$ sed -n 's/[[:digit:]]/&/p' gpl-3.0.txt |
地址范围
我们可以指定要处理的文本流的特定部分。它可以是行的静态位置,也可以是行范围。在第一个示例中,我们将打印 GPL v3 文本文件中的第 5 行:
|
1 |
$ sed -n '5p' gpl-3.0.txt |
除了单行之外,我们还可以指定要处理的行范围。在这里,我们给出了从第 5 行到第 9 行(共 5 行)的地址范围,sed 将对其进行操作:
|
1 |
$ sed -n '5,9p' gpl-3.0.txt |
指定行地址也有不同的方法。除了我们自己确定行号之外,我们还可以重新排列前面的示例,以便 sed 将从第 5 行开始,并对接下来的 5 行进行操作:
|
1 |
$ sed -n '5,+5p' gpl-3.0.txt |
另一种指定行的方法是使用间隔。在下一个示例中,sed 将从第 1 行开始,并对每隔一行进行操作:
|
1 |
$ sed -n '1~2p' gpl-3.0.txt |
文本删除
到目前为止,我们已经学习了如何打印目标文本行。除了打印,我们还可以从输出中删除这些行。在下面的示例中,我们将从开头删除多行。在这里,我们不需要使用选项 -n,因为我们希望 sed 打印其他所有未删除的内容。对于行删除,我们将使用选项 d:
|
1 |
$ sed '1~2d' gpl-3.0.txt |
请注意,源文件仍然完好无损。Sed 只是在输出过程中执行行删除。如果需要,您可以将 sed 输出保存到文件中。您可以覆盖原始文件或将其另存为其他文件:
|
1 |
$ sed '1~2d' gpl-3.0.txt > gpl-3.0.modified.txt |
除了手动将输出写入文件之外,sed 还可以对原始文件进行就地编辑。简而言之,sed 将编辑原始文件并写入所做的任何更改。此方法会覆盖原始文件,因此应谨慎使用:
|
1 |
$ sed -i '1~2d' gpl-3.0.txt |
由于就地编辑很危险,sed 自带了备份功能。在进行就地编辑时,请使用 -i.bak 代替 -i,以便在编辑前进行备份。Sed 将创建带有 .bak 扩展名的备份文件:
|
1 |
$ sed -i.bak '1~2d' gpl-3.0.txt |
文本替换
到目前为止,这是 sed 最常见的应用之一。它搜索文本模式并用给定的文本替换该模式。在这里,文本模式是用正则表达式(简称 regex)描述的。要了解有关使用正则表达式的更多信息,请参考本教程,其中概述了如何结合正则表达式使用 Grep 来搜索文本模式。
以下是使用正则表达式进行最基本文本替换的示例:
|
1 |
$ 's/<search_pattern>/<replacement>' |
在这里,s 是替换命令。斜杠是模式和替换内容的定界符。让我们把它付诸实践:
|
1 |
$ echo "hello world" | sed 's/hello/HELLO/' |
下一个示例将演示下划线(_)的用法。在这里,下划线将充当定界符:
|
1 |
$ echo http://example.com/index.html | sed 's_com/index_net/home_' |
在这里,我们正在搜索 com/index 并将其更改为 net/home。 请注意下划线的位置,因为它们非常关键。例如,如果漏掉了最后一个下划线,sed 将报错:
|
1 |
$ echo "http://www.example.com/index.html" | sed 's_com/index_net/home' |
我们需要一个临时文件来练习一些替换。在这里,我有一个裁剪版的 GPL v3 文本文件:
|
1 |
$ cat gpl-3.0.cropped.txt |
让我们进行一些基本的文本替换:
|
1 |
$ cat gpl-3.0.cropped.txt | sed 's/GNU/GNU is Not Unix/' |
看看下一个例子。我们想把所有的 the 替换为 THE :
|
1 |
$ echo "the the quick brown fox jumps over the lazy dog" | sed 's/the/THE/' |
注意到什么了吗?Sed 并没有改变所有的 the。 事实上,它只改变了第一个。这是怎么回事?这是选项 s 的默认行为。它仅匹配给定行的第一个实例,然后移动到下一行。为了确保 sed 检查整行以查找搜索模式,我们需要使用一个可选标志 g。让我们修正这个命令:
|
1 |
$ echo "the the quick brown fox jumps over the lazy dog" | sed 's/the/THE/g' |
现在它按预期工作了。使用该命令的另一个有趣方式是指定要更改的实例数量。在前面的示例中,有 3 个 the,对吧?如果我们指定只更改第 3 个 实例?更改将发生在可选标志处:
|
1 |
$ echo "the the quick brown fox jumps over the lazy dog" | sed 's/the/THE/3' |
If you’re working with a big text file, then it may help if sed printed only those lines where the substitutions took place. To achieve that, we need to add another additional flag p:
|
1 |
$ sed -n 's/GNU/GNU is Not Unix/gp' gpl-3.0.txt |
Case Sensitivity
By default, all the sed operations are case-sensitive. The following command will demonstrate the default behavior of case sensitivity:
|
1 |
$ echo "HELLO WORLD" | sed 's/hello/hElLo/' |
Because of the case mismatch, there’s no change. In such a situation, we can tell sed to disable case sensitivity. To do so, add the optional flag i:
|
1 |
$ echo "HELLO WORLD" | sed 's/hello/hElLo/i' |
How to Replace and Reference Texts
的强大之处sed 主要在于它使用正则表达式的能力。通过更高级和复杂的正则表达式模式,我们可以完成更多工作。例如,我们可以将文本从文件的开头替换到某个特定位置。看看以下表达式:
|
1 |
$ sed 's/^.*GNU/GNU_replaced/' gpl-3.0.txt |
这里,脱字符 (^) 表示行首。匹配任意字符的运算符是用句点表示的 (.). 星号 (*) 是通配符表达式,从行首一直匹配到 GNU.
另一个有趣的技巧是使用 & 符号。我们可以用它来突出显示 sed 找到搜索模式的区域:
|
1 |
$ sed 's/^.*GNU/(&)/' gpl-3.0.txt |
结语
在本教程中,我们探索了 sed 命令的基础知识。我们学习了如何打印特定行、搜索文本、删除和替换文本、重写文本以及使用正则表达式。一个构建合理的 sed 命令可以极大地改变文本文件。现在,您可以在 Linux 中成功操作文本,借助 sed.
祝您使用愉快!









评论
暂无评论。发表第一条评论吧。