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

介绍

sed命令,缩写为 stream editor,对来自标准输入或文件的文本执行编辑操作。

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

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

<$>[注] :本教程使用在Ubuntu和其他Linux操作系统上发现的GNU版本的sed。如果你使用macOS,你将有BSD版本,其中有不同的选项和论点。你可以使用brew install gnu-sed安装sed的GNU版本。

基本使用

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

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

基本用途是:

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

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

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

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

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

让我们使用sed来查看BSD许可证文件的内容。sed默认地将其结果发送到屏幕上,这意味着您可以通过没有编辑命令将其用作文件阅读器。

1sed '' BSD

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

 1[secondary_label Output]
 2Copyright (c) The Regents of the University of California.
 3All rights reserved.
 4
 5Redistribution and use in source and binary forms, with or without
 6modification, are permitted provided that the following conditions
 7are met:
 81. Redistributions of source code must retain the above copyright
 9    notice, this list of conditions and the following disclaimer.
102. Redistributions in binary form must reproduce the above copyright
11    notice, this list of conditions and the following disclaimer in the
12    documentation and/or other materials provided with the distribution.
13...
14...

单个引文包含你转移到sed的编辑命令. 在这种情况下,你没有传输任何东西,所以sed打印了它接收的每个行到标准输出。

sed 可以使用标准输入而不是文件,将 cat 命令的输出导向 sed 以产生相同的结果:

1cat BSD | sed ''

你会看到文件的输出:

 1[secondary_label Output]
 2Copyright (c) The Regents of the University of California.
 3All rights reserved.
 4
 5Redistribution and use in source and binary forms, with or without
 6modification, are permitted provided that the following conditions
 7are met:
 81. Redistributions of source code must retain the above copyright
 9    notice, this list of conditions and the following disclaimer.
102. Redistributions in binary form must reproduce the above copyright
11    notice, this list of conditions and the following disclaimer in the
12    documentation and/or other materials provided with the distribution.
13. . .
14. . .

正如您所看到的,您可以轻松地操作文件或文本流,如在输出管道时产生的文件或文本流。

印刷线路

在之前的示例中,您看到输入转换为sed而没有任何操作将直接打印结果到标准输出。

让我们探索sed的明确打印命令,您通过在单个引文中使用p字符来指定。

执行以下命令:

1sed 'p' BSD

您将看到BSD文件的每个行打印两次:

 1[secondary_label Output]
 2Copyright (c) The Regents of the University of California.
 3Copyright (c) The Regents of the University of California.
 4All rights reserved.
 5All rights reserved.
 6
 7Redistribution and use in source and binary forms, with or without
 8Redistribution and use in source and binary forms, with or without
 9modification, are permitted provided that the following conditions
10modification, are permitted provided that the following conditions
11are met:
12are met:
13. . .
14. . .

默认情况下,sed 会自动打印每个行,然后你告诉它用p命令明确打印行,这样你就可以每行打印两次。

如果你仔细检查输出,你会看到它有第一个行两次,然后是第二行两次,等等,这告诉你sed在数据行后行操作。

您可以通过将-n选项转换为sed来清理结果,从而抑制自动打印:

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

现在我们再次打印每行一次。

迄今为止的例子几乎不能被认为是编辑(除非你想打印每行两次...).接下来,你将探索sed如何通过针对文本数据的特定部分来修改输出。

使用地址范围

地址允许您针对文本流的特定部分,您可以指定一个特定的行或甚至一系列的行。

让我们打印了文件的第一个行,执行以下命令:

1sed -n '1p' BSD

第一行打印到屏幕上:

1[secondary_label Output]
2Copyright (c) The Regents of the University of California.

通过在打印命令前放置数字1,你说SED是要操作的行数,你可以轻松打印五行(不要忘记-n):

1sed -n '1,5p' BSD

你会看到这个输出:

1[secondary_label Output]
2Copyright (c) The Regents of the University of California.
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions

如果你给sed一个地址,它只会执行这些行之后的命令. 在本示例中,你已经告诉sed打印一行到五行。

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

这将导致相同的输出,因为你告诉SED从1行开始,然后在接下来的4行上运行。

如果您想打印所有其他行,请在~字符之后指定间隔. 以下命令打印了BSD文件中的每个其他行,从一行开始:

1sed -n '1~2p' BSD

以下是你会看到的输出:

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

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

删除文本

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

在这种情况下,您不再需要n命令,因为sed将打印所有未删除的内容,这将帮助您看到正在发生的事情。

更改上一节中的最后一个命令,使它 删除第一个开始的所有其他行:

1sed '1~2d' BSD

结果是,你会看到你上次没有给出的每一行:

 1[secondary_label Output]
 2All rights reserved.
 3Redistribution and use in source and binary forms, with or without
 4are met:
 5    notice, this list of conditions and the following disclaimer.
 6    notice, this list of conditions and the following disclaimer in the
 73. Neither the name of the University nor the names of its contributors
 8    without specific prior written permission.
 9. . .
10. . .

重要的是要注意,我们的源文件没有受到影响. 它仍然不受影响. 编辑是输出到我们的屏幕。

如果我们想保存我们的编辑,我们可以将标准输出重定向到这样的文件:

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

现在打开的文件:

1cat everyother.txt

您可以看到您之前在屏幕上看到的相同的输出:

 1[secondary_label Output]
 2All rights reserved.
 3Redistribution and use in source and binary forms, with or without
 4are met:
 5    notice, this list of conditions and the following disclaimer.
 6    notice, this list of conditions and the following disclaimer in the
 73. Neither the name of the University nor the names of its contributors
 8    without specific prior written permission.
 9. . .
10. . .

默认情况下,sed命令不会编辑源文件,但您可以通过-i选项来改变这种行为,这意味着执行编辑

<$>[warning] 警告:使用 -i 交换机将重写原始文件,所以您应该仔细使用它。 首先在没有 -i 交换机的情况下执行操作,然后再次使用 -i 执行命令,一旦您有所需的东西,创建原始文件的备份副本,或重定向输出到一个文件。 使用 -i 交换机随机更改原始文件非常容易。

让我们通过编辑您刚刚创建的everyother.txt文件来尝试,让我们通过再次删除每个其他行 来进一步缩小文件:

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

如果您使用「cat」來顯示「cat everyother.txt」的檔案,您會看到該檔案已被編輯。

-i 选项可能是 **危险的 **. 幸运的是, sed 允许您在编辑之前创建备份文件。

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

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

这会创建一个备份文件,并使用.bak 扩展,然后在原始文件中进行编辑。

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

替代文本

也许sed的最著名的用途是代替文本,sed可以使用常规表达式搜索文本模式,然后用其他东西替换所发现的文本。

您可以了解有关常规表达式的更多信息,如遵循 使用 Grep 常规表达式在 Linux 中搜索文本模式

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

1's/old_word/new_word/'

「s」是替代命令. 三个切片(/)用于分离不同的文本字段. 如果更有用的话,您可以使用其他字符来划界字段。

例如,如果您试图更改网站名称,使用另一个分界器将是有帮助的,因为 URL 包含切片。

執行下列命令以打印「Echo」的 URL,並用「sed」修改它,使用「subscore(`_')」字符作為界限:

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

这将com/index取代org/home

1[secondary_label Output]
2http://www.example.org/home.html

不要忘记最后的界限,或者sed会抱怨。

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

你会看到这个输出:

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

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

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

现在让我们用前进来代替,使用以下命令:

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

结果看起来像这样:

1[secondary_label Output]
2this is the sforwardg that never ends
3yes, it goes forward and on, my friend
4some people started singing it
5not knowing what it was
6and they'll cforwardtinue singing it forever
7just because...

你可以在这里看到一些值得注意的事情。第一,是取代了模式,而不是单词。

另一个要注意的是,在第二行,第二个没有被更改为前进

这是因为默认情况下,s命令运行在一行中的第一个匹配,然后移动到下一行. 要让sed取代on的每个实例,而不是每个行上的第一个,您必须将可选的旗帜传递给替代命令。

向替代命令提供g旗,将其放置在替代集之后:

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

你会看到这个输出:

1[secondary_label Output]
2this is the sforwardg that never ends
3yes, it goes forward and forward, my friend
4some people started singing it
5not knowing what it was
6and they'll cforwardtinue singing it forever
7just because...

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

如果你只想更改每个行上找到的on的第二个实例,那么你会使用数字2而不是g:

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

这一次,其它行没有改变,因为它们没有第二次发生:

1[secondary_label Output]
2this is the song that never ends
3yes, it goes on and forward, my friend
4some people started singing it
5not knowing what it was
6and they'll continue singing it forever
7just because...

如果您只想看到哪些行被更换,请再次使用n选项来抑制自动打印。

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

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

改变了打印到屏幕的行:

1[secondary_label Output]
2yes, it goes on and forward, my friend

正如您所看到的,您可以在命令的末尾组合旗帜。

如果您希望搜索流程忽略案例,您可以通过i旗。

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

以下是你会看到的输出:

1[secondary_label Output]
2this is the song that never ends
3yes, it goes on and on, my friend
4some people started saying it
5not knowing what it was
6and they'll continue saying it forever
7just because...

替换和引用匹配的文本

如果您想要找到具有常规表达式的更复杂的模式,您可以在替代文本中引用匹配的模式的若干不同的方法。

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

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

你会看到这个输出:

1[secondary_label Output]
2REPLACED never ends
3yes, it goes on and on, my friend
4some people started singing it
5REPLACED it was
6and they'll continue singing it forever
7just because...

您可以看到野卡表达式从行开始到at的最后一个实例相匹配。

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

让我们在匹配的文本周围放下子:

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

你会看到这个输出:

1[secondary_label Output]
2(this is the song that) never ends
3yes, it goes on and on, my friend
4some people started singing it
5(not knowing what) it was
6and they'll continue singing it forever
7just because...

更灵活地引用匹配的文本的方法是使用逃离的关节来组合匹配的文本的部分。

每个标记为的搜索文本组都可以被引用一个逃脱的引用号码,例如,第一个组可以被引用\1,第二个被引用\2等等。

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

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

你会看到这个输出:

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

例如,第二行跳过了第一句话,因为它有一个字符不在我们的字符集中。

让我们改进正规表达式,以便更准确:

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

你会看到这个输出:

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

这是比上次好得多,这组点数与相关的单词。

请注意,我们如何在窗口中重复表达式(一次没有*字符,然后一次用它)。这是因为*字符匹配前面的字符集为零或多次,这意味着与野卡的匹配将被视为匹配,即使没有找到模式。

要确保sed至少找到文本一次,您必须在使用wildcard之前与它匹配一次。

结论

在本教程中,你探索了sed命令. 你从文件中打印了特定行,搜索了文本,删除了行,重写了原始文件,并使用了常规表达式来代替文本。

在本系列的下一篇文章中(https://andsky.com/tech/tutorials/intermediate-sed-manipulating-streams-of-text-in-a-linux-environment),您将探索一些更先进的功能。

Published At
Categories with 技术
comments powered by Disqus