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

介绍

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

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

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

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

启动互动终端!

基本用法

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

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

基本用法是:

  • sed [options] commands [file-to-edit]

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

  • cd
  • cp /usr/share/common-licenses/BSD .

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

  • cat << 'EOF' > BSD
  • 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.
  • 3. Neither the name of the University nor the names of its contributors
  • may be used to endorse or promote products derived from this software
  • without specific prior written permission.
  • THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  • ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  • IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  • ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  • FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  • DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  • OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  • HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  • LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  • OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  • SUCH DAMAGE.
  • EOF

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

  • 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以产生相同的结果:

  • 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单引号内字符来指定该命令

执行以下命令:

  • 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,这会抑制自动打印:

  • 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打印文件的第一行。执行以下命令:

  • sed -n '1p' BSD

第一行打印到屏幕上:

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

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

  • 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 行进多少行,以不同的方式指定它,如下所示:

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

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

如果要每隔一行打印一次,请在~字符后指定间隔以下命令BSD从第 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将打印所有未删除的内容。这将帮助您了解正在发生的事情。

修改上一节中的最后一个命令,使其

从第一行开始每隔一行删除:

  • 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. . . . . . .

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

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

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

现在打开文件cat

  • 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就地编辑您刚刚创建文件来尝试一下让我们通过

再次
删除每隔一行来进一步缩小文件

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

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

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

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

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

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

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

替换文本

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

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

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

's/old_word/new_word/'

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

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

执行以下命令以使用下划线 ( ) 字符作为分隔符打印 URLecho并使用 修改它sed_

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

这替换com/indexorg/home. 输出显示修改后的 URL:

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

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

  • 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

  • echo "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..." > song.txt

现在让我们来代替表达onforward使用以下命令:

  • 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替换的模式,而不是单词。on范围内song更改为forward

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

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

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

  • 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...

现在替换命令会更改每个实例。

如果你只是想改变的二审“关于”各行的sed的发现,那么你可以使用的数量2,而不是g

  • 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选项传递给替换命令以打印发生替换的行。

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

更改后的行打印到屏幕上:

Output
yes, it goes on and forward, my friend

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

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

  • 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,请使用以下命令:

  • 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

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

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

  • 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,第二个用引用\2依此类推。

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

  • sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/ /' 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...

如您所见,结果并不完美。例如,第二行跳过第一个单词,因为它有一个未在我们的字符集中列出的字符。同样,它they'll在第五行中将其视为两个单词。

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

  • sed 's/\([^ ][^ ]*\) \([^ ][^ ]*\)/ /' 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 命令快速转换文本文档。

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

觉得文章有用?

点个广告表达一下你的爱意吧 !😁