在 Linux 中使用 Sed 流编辑器操作文本的基础知识在 Linux 中使用 Sed 流编辑器操作文本的基础知识在 Linux 中使用 Sed 流编辑器操作文本的基础知识在 Linux 中使用 Sed 流编辑器操作文本的基础知识
  • 文章
  • 正则表达式
    • 工具
  • 登录
找到的结果: {phrase} (显示: {results_count} 共: {results_count_total})
显示: {results_count} 共: {results_count_total}

加载更多搜索结果...

搜索范围
模糊匹配
搜索标题
搜索内容
发表 admin at 2025年2月28日
类别
  • 未分类
标签

在 Linux 中使用 Sed 流编辑器操作文本的基础知识

介绍

sed 命令是流编辑器的缩写,对来自标准输入或文件的文本执行编辑操作。 sed 以非交互方式逐行编辑。

这意味着您在调用命令时做出所有编辑决定,sed 会自动执行指令。这可能看起来令人困惑或不直观,但它是一种非常强大且快速的文本转换方式,尤其是作为脚本或自动化工作流程的一部分。

本教程将涵盖一些基本操作,并向您介绍操作此编辑器所需的语法。您几乎肯定永远不会用 sed 替换您的常规文本编辑器,但它可能会成为您的文本编辑工具箱中受欢迎的补充。

注意:本教程使用在 Ubuntu 和其他 Linux 操作系统上找到的 sed 的 GNU 版本。如果您使用的是 macOS,您将拥有具有不同选项和参数的 BSD 版本。您可以使用 brew install gnu-sed 使用 Homebrew 安装 GNU 版本的 sed。

基本用法

sed 对从文本文件或标准输入 (STDIN) 读取的文本流进行操作。这意味着您可以将另一个命令的输出直接发送到 sed 进行编辑,或者您可以处理您已经创建的文件。

您还应该知道 sed 默认情况下将所有内容输出到标准输出 (STDOUT)。这意味着,除非重定向,否则 sed 会将其输出打印到屏幕上,而不是将其保存在文件中。

基本用法是:

  1. sed [options] commands [file-to-edit]

在本教程中,您将使用 BSD 软件许可证的副本来试验 sed。在 Ubuntu 上,执行以下命令将 BSD 许可证文件复制到您的主目录,以便您可以使用它:

  1. cd
  2. cp /usr/share/common-licenses/BSD .

如果您没有 BSD 许可证的本地副本,请使用以下命令自行创建一个:

  1. cat << 'EOF' > BSD
  2. Copyright (c) The Regents of the University of California.
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7. 1. Redistributions of source code must retain the above copyright
  8. notice, this list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright
  10. notice, this list of conditions and the following disclaimer in the
  11. documentation and/or other materials provided with the distribution.
  12. 3. Neither the name of the University nor the names of its contributors
  13. may be used to endorse or promote products derived from this software
  14. without specific prior written permission.
  15. THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  16. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  19. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. SUCH DAMAGE.
  26. EOF

让我们使用 sed 查看 BSD 许可证文件的内容。 sed 默认将其结果发送到屏幕,这意味着您可以通过不向其传递任何编辑命令将其用作文件阅读器。尝试执行以下命令:

  1. sed '' BSD

你会看到 BSD 许可证显示在屏幕上:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ... ...

单引号包含您传递给 sed 的编辑命令。在这种情况下,您什么也没有传递给它,所以 sed 将它接收到的每一行打印到标准输出。

sed 可以使用标准输入而不是文件。将 cat 命令的输出通过管道传输到 sed 以产生相同的结果:

  1. cat BSD | sed ''

您将看到文件的输出:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . . . . . .

如您所见,您可以对文件或文本流进行操作,就像使用竖线 (|) 字符对输出进行管道传输时产生的操作一样容易。

印刷线

在前面的示例中,您看到在没有任何操作的情况下传递到 sed 的输入会将结果直接打印到标准输出。

让我们探索 sed 的显式 print 命令,您可以使用单引号内的 p 字符指定该命令。

执行以下命令:

  1. sed 'p' BSD

您会看到 BSD 文件的每一行都打印了两次:

Output
Copyright (c) The Regents of the University of California. Copyright (c) The Regents of the University of California. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions are met: are met: . . . . . .

默认情况下,sed 会自动打印每一行,然后您已告诉它使用 \p 命令显式打印行,因此您将每行打印两次。

如果仔细检查输出,您会发现第一行两次,第二行两次,依此类推,这告诉您 sed 逐行处理数据。它读取一行,对其进行操作,并输出结果文本,然后在下一行重复该过程。

您可以通过将 -n 选项传递给 sed 来清理结果,这会抑制自动打印:

  1. sed -n 'p' BSD
Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. . . . . . .

我们现在回到打印每行一次。

到目前为止的例子很难被认为是编辑(除非你想每行打印两次......)。接下来,您将探索 sed 如何通过定位文本数据的特定部分来修改输出。

使用地址范围

地址使您可以定位文本流的特定部分。您可以指定特定行,甚至可以指定一系列行。

让我们让 sed 打印文件的第一行。执行以下命令:

  1. sed -n '1p' BSD

第一行打印到屏幕:

Output
Copyright (c) The Regents of the University of California.

通过在打印命令之前放置数字 1,您告诉 sed 要操作的行号。您可以轻松地打印五行(不要忘记 \-n):

  1. sed -n '1,5p' BSD

你会看到这个输出:

Output
Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions

您刚刚为 sed 提供了一个地址范围。如果您给 sed 一个地址,它只会执行这些行后面的命令。在此示例中,您已经告诉 sed 打印第 1 行到第 5 行。您可以通过提供第一个地址然后使用偏移量告诉 sed 要行进多少行,以不同的方式指定它,如下所示:

  1. sed -n '1,+4p' BSD

这将产生相同的输出,因为您告诉 sed 从第 1 行开始,然后也对接下来的 4 行进行操作。

如果要每隔一行打印一次,请在 ~ 字符后指定间隔。以下命令打印 BSD 文件中的每隔一行,从第 1 行开始:

  1. sed -n '1~2p' BSD

这是您将看到的输出:

Output
Copyright (c) The Regents of the University of California. modification, are permitted provided that the following conditions 1. Redistributions of source code must retain the above copyright 2. Redistributions in binary form must reproduce the above copyright documentation and/or other materials provided with the distribution. may be used to endorse or promote products derived from this software . . . . . .

您也可以使用 sed 从输出中删除文本。

删除文本

通过将 p 命令更改为 d 命令,您可以在之前指定文本打印的位置执行文本删除。

在这种情况下,您不再需要 -n 命令,因为 sed 将打印所有未删除的内容。这将帮助您了解发生了什么。

修改上一节中的最后一个命令以使其成为

  1. sed '1~2d' BSD

结果是您看到了上次未提供的每一行:

Output
All rights reserved. Redistribution and use in source and binary forms, with or without are met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the 3. Neither the name of the University nor the names of its contributors without specific prior written permission. . . . . . .

重要的是要注意我们的源文件没有受到影响。它仍然完好无损。编辑输出到我们的屏幕。

如果我们想保存我们的编辑,我们可以将标准输出重定向到一个文件,如下所示:

  1. sed '1~2d' BSD > everyother.txt

现在用 cat 打开文件:

  1. cat everyother.txt

您会看到与之前在屏幕上看到的相同的输出:

Output
All rights reserved. Redistribution and use in source and binary forms, with or without are met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the 3. Neither the name of the University nor the names of its contributors without specific prior written permission. . . . . . .

默认情况下,sed 命令不编辑源文件,但您可以通过传递 -i 选项来更改此行为,这意味着“就地执行编辑”。这将改变源文件。

警告:使用 -i 开关会覆盖原始文件,因此您应该谨慎使用。首先执行不使用 -i 开关的操作,然后在获得所需内容后使用 -i 再次运行命令,创建原始文件的备份,或重定向输出到一个文件。使用 -i 开关很容易意外更改原始文件。

让我们通过就地编辑刚刚创建的 everyother.txt 文件来尝试一下。让我们通过删除每隔一行来进一步减少文件

  1. sed -i '1~2d' everyother.txt

如果您使用 cat 显示包含 cat everyother.txt 的文件,您将看到该文件已被编辑。

-i 选项可能很危险。值得庆幸的是,sed 使您能够在编辑之前创建备份文件。

要在编辑前创建备份文件,请直接在“-i”选项后添加备份扩展名:

  1. sed -i.bak '1~2d' everyother.txt

这将创建一个扩展名为 .bak 的备份文件,然后就地编辑原始文件。

接下来您将了解如何使用 sed 执行搜索和替换操作。

替换文本

也许 sed 最著名的用途是替换文本。 sed 可以使用正则表达式搜索文本模式,然后用其他内容替换找到的文本。

您可以按照使用 Grep 正则表达式在 Linux 中搜索文本模式来了解有关正则表达式的更多信息。

在最基本的形式中,您可以使用以下语法将一个词更改为另一个词:

's/old_word/new_word/'

s 是替换命令。三个斜杠 (/) 用于分隔不同的文本字段。如果更有帮助,您可以使用其他字符来分隔字段。

例如,如果您尝试更改网站名称,使用另一个分隔符会有所帮助,因为 URL 包含斜杠。

执行以下命令,用echo打印一个URL,用sed修改,使用下划线(_)字符作为分隔符:

  1. echo "http://www.example.com/index.html" | sed 's_com/index_org/home_'

这会将 com/index 替换为 org/home。输出显示修改后的 URL:

Output
http://www.example.org/home.html

不要忘记最后的分隔符,否则 sed 会报错。如果您运行此命令:

  1. echo "http://www.example.com/index.html" | sed 's_com/index_org/home'

你会看到这个输出:

Output
sed: -e expression #1, char 20: unterminated `s' command

让我们创建一个新文件来练习一些替换。执行以下命令创建一个名为 song.txt 的新文本文件:

  1. echo "this is the song that never ends
  2. yes, it goes on and on, my friend
  3. some people started singing it
  4. not knowing what it was
  5. and they'll continue singing it forever
  6. just because..." > song.txt

现在让我们将表达式 on 替换为 forward。使用以下命令:

  1. sed 's/on/forward/' song.txt

输出如下所示:

Output
this is the sforwardg that never ends yes, it goes forward and on, my friend some people started singing it not knowing what it was and they'll cforwardtinue singing it forever just because...

你可以在这里看到一些值得注意的事情。首先,sed 替换了模式,而不是单词。 song 中的on 改为forward。

另一件需要注意的事情是,在第 2 行,第二个 on 没有更改为 forward。

这是因为默认情况下,s 命令对一行中的第一个匹配项进行操作,然后移至下一行。要使 sed 替换 on 的每个实例而不是每行的第一个实例,您必须将一个可选标志传递给 substitute 命令。

通过将 g 标志放在替换集之后,将其提供给替换命令:

  1. sed 's/on/forward/g' song.txt

你会看到这个输出:

Output
this is the sforwardg that never ends yes, it goes forward and forward, my friend some people started singing it not knowing what it was and they'll cforwardtinue singing it forever just because...

现在 substitute 命令改变了每个实例。

如果您仅想要更改 sed 在每一行中找到的 \on 的第二个实例,那么您将使用数字 2 而不是 g:

  1. sed 's/on/forward/2' song.txt

这次其他行没有变化,因为它们没有第二次出现:

Output
this is the song that never ends yes, it goes on and forward, my friend some people started singing it not knowing what it was and they'll continue singing it forever just because...

如果您只想查看替换了哪些行,请再次使用 -n 选项来禁止自动打印。

然后,您可以将 p 选项传递给 substitute 命令以打印发生替换的行。

  1. sed -n 's/on/forward/2p' song.txt

更改的行打印到屏幕上:

Output
yes, it goes on and forward, my friend

如您所见,您可以在命令末尾组合标志。

如果您希望搜索过程忽略大小写,您可以将 \i 标志传递给它。

  1. sed 's/SINGING/saying/i' song.txt

这是您将看到的输出:

Output
this is the song that never ends yes, it goes on and on, my friend some people started saying it not knowing what it was and they'll continue saying it forever just because...

替换和引用匹配的文本

如果您想使用正则表达式查找更复杂的模式,可以使用多种不同的方法在替换文本中引用匹配的模式。

例如,要从行的开头匹配到 at,请使用以下命令:

  1. sed 's/^.*at/REPLACED/' song.txt

你会看到这个输出:

Output
REPLACED never ends yes, it goes on and on, my friend some people started singing it REPLACED it was and they'll continue singing it forever just because...

您可以看到通配符表达式从行的开头匹配到 at 的最后一个实例。

由于您不知道将在搜索字符串中匹配的确切短语,您可以使用 & 字符来表示替换字符串中的匹配文本。

让我们在匹配的文本周围加上括号:

  1. sed 's/^.*at/(&)/' song.txt

你会看到这个输出:

Output
(this is the song that) never ends yes, it goes on and on, my friend some people started singing it (not knowing what) it was and they'll continue singing it forever just because...

引用匹配文本的更灵活的方法是使用转义括号对匹配文本的部分进行分组。

每组标有括号的搜索文本都可以通过转义参考号来引用。例如,第一个括号组可以用 引用,第二个括号组用 等等。

在这个例子中,我们将交换每行的前两个词:

  1. sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' song.txt

你会看到这个输出:

Output
is this the song that never ends yes, goes it on and on, my friend people some started singing it knowing not what it was they and'll continue singing it forever because just...

如您所见,结果并不完美。例如,第二行会跳过第一个单词,因为它有一个字符未在我们的字符集中列出。类似地,它将 theyll 视为第五行中的两个词。

让我们改进正则表达式以使其更准确:

  1. sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/\2 \1/' song.txt

你会看到这个输出:

Output
is this the song that never ends it yes, goes on and on, my friend people some started singing it knowing not what it was they'll and continue singing it forever because... just

这比上次好多了。这会将标点符号与相关词组合在一起。

注意我们如何重复括号内的表达式(一次没有 * 字符,然后一次有它)。这是因为 * 字符与其之前的字符集匹配零次或多次。这意味着即使未找到模式,与通配符的匹配也将被视为“匹配”。

为确保 sed 至少找到一次文本,在使用通配符之前必须在不使用通配符的情况下匹配一次。

结论

在本教程中,您探索了 sed 命令。您打印文件中的特定行、搜索文本、删除行、覆盖原始文件并使用正则表达式替换文本。您应该已经能够看到如何使用正确构造的 sed 命令快速转换文本文档。

在本系列的下一篇文章中,您将探索一些更高级的功能。

©2015-2025 艾丽卡 support@alaica.com