📅  最后修改于: 2020-10-16 06:18:57             🧑  作者: Mango
我们已经讨论了模式和保持缓冲区的用法。在本章中,我们将进一步探讨它们的用法。让我们讨论打印模式空间的n命令。它将与其他命令结合使用。下面给出的是n命令的语法。
[address1[,address2]]n
让我们举个例子。
[jerry]$ sed 'n' books.txt
执行以上代码后,将产生以下结果:
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864
n命令打印模式缓冲区的内容,清除模式缓冲区,将下一行取到模式缓冲区中,并在其上应用命令。
让我们考虑有三个SED命令之前n和具体如下●2个SED命令:
Sed command #1
Sed command #2
Sed command #3
n command
Sed command #4
Sed command #5
在这种情况下,SED在模式缓冲区上应用前三个命令,清除模式缓冲区,将下一行提取到模式缓冲区中,然后在其上应用第四和第五个命令。这是一个非常重要的概念。如果没有对此有清晰的了解,请不要继续。
保留缓冲区保留数据,但是SED命令不能直接应用于保留缓冲区。因此,我们需要将保持缓冲区数据带入模式缓冲区。 SED提供x命令来交换模式和保持缓冲区的内容。以下命令说明了x命令。
让我们稍微修改books.txt文件。说,该文件包含书名及其作者姓名。修改后,文件应如下所示:
[jerry]$ cat books.txt
执行上述代码后,您将得到以下结果:
A Storm of Swords
George R. R. Martin
The Two Towers
J. R. R. Tolkien
The Alchemist
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
Paulo Coelho
A Game of Thrones
George R. R. Martin
让我们交换两个缓冲区的内容。例如,以下示例仅打印作者的姓名。
[jerry]$ sed -n 'x;n;p' books.txt
执行上述代码后,您将得到以下结果:
George R. R. Martin
J. R. R. Tolkien
Paulo Coelho
J. R. R. Tolkien
Paulo Coelho
George R. R. Martin
让我们了解此命令的工作原理。
最初,SED将第一行(即“剑之风暴”)读入模式缓冲区。
x命令将此行移至保持缓冲区。
n将下一行(即George RR Martin)提取到模式缓冲区中。
控制传递给命令,后跟n,该命令将打印模式缓冲区的内容。
重复该过程,直到文件耗尽。
现在让我们在打印之前交换缓冲区的内容。猜猜,会发生什么?是的,它会打印书籍的标题。
[jerry]$ sed -n 'x;n;x;p' books.txt
执行上述代码后,您将得到以下结果:
A Storm of Swords
The Two Towers
The Alchemist
The Fellowship of the Ring
The Pilgrimage
A Game of Thrones
h命令处理保留缓冲区。它将数据从模式缓冲区复制到保持缓冲区。保留缓冲区中的现有数据将被覆盖。请注意, h命令不会移动数据,而只会复制数据。因此,复制的数据将保留在模式缓冲区中。下面给出的是h命令的语法。
[address1[,address2]]h
以下命令仅打印作者Paulo Coelho的标题。
[jerry]$ sed -n '/Paulo/!h; /Paulo/{x;p}' books.txt
执行上述代码后,您将得到以下结果:
The Alchemist
The Pilgrimage
让我们了解以上命令的工作原理。 books.txt的内容采用特定格式。第一行是书名,其后是书的作者。在上面的命令中,“!”用于反转条件,即仅当模式匹配不成功时才将行复制到保持缓冲区。花括号{}用于对多个SED命令进行分组
在命令的第一遍中,SED将第一行(即《剑之风暴》)读入模式缓冲区,并检查其是否包含模式Paulo。由于模式匹配不成功,因此将这一行复制到保持缓冲区。现在,模式缓冲区和保持缓冲区都包含同一行,即“剑风暴”。在第二步中,它检查该行是否包含模式Paulo。由于模式不匹配,因此不会执行任何操作。
在第二遍中,它将下一行George RR Martin读入模式缓冲区,并应用相同的步骤。对于接下来的三行,它执行相同的操作。在第五遍结束时,两个缓冲区都包含The Alchemist。在第六遍开始时,它将读取Paulo Coelho行,并且在模式匹配时,不会将该行复制到保持缓冲区中。因此,模式缓冲区包含Paulo Coelho,而保持缓冲区包含The Alchemist。
此后,它检查模式缓冲区是否包含模式Paulo。模式匹配成功后,它将与保持缓冲区交换模式缓冲区的内容。现在,模式缓冲区包含炼金术士,而保持缓冲区包含Paulo Coelho。最后,它打印模式缓冲区的内容。相同的步骤应用于“朝圣”模式。
h命令破坏保留缓冲区的先前内容。这并不总是可以接受的,因为有时我们需要保留内容。为此,SED提供了H命令,该命令通过在末尾添加新行来将内容附加到保持缓冲区。 h和H命令之间的唯一区别是,前者将覆盖保留缓冲区中的数据,而后者将数据追加到保留缓冲区中。它的语法类似于h命令。
[address1[,address2]]H
让我们再举一个例子。这次,不仅打印书名,还打印其作者的姓名。以下示例打印书名及其作者姓名。
[jerry]$ sed -n '/Paulo/!h; /Paulo/{H;x;p}' books.txt
执行上述代码后,您将得到以下结果:
The Alchemist
Paulo Coelho
The Pilgrimage
Paulo Coelho
我们学习了如何将模式缓冲区的内容复制/追加到保持缓冲区。我们也可以执行反向函数吗?是的,当然了!为此,SED提供了g命令,该命令将数据从保持缓冲区复制到模式缓冲区。复制时,来自模式空间的现有数据将被覆盖。下面给出的是g命令的语法。
[address1[,address2]]g
让我们考虑相同的示例-打印书名及其作者。这次,我们将首先打印作者的姓名,并在下一行上打印相应的书名。以下命令将打印作者Paulo Coelho的姓名,以及其书名。
[jerry]$ sed -n '/Paulo/!h; /Paulo/{p;g;p}' books.txt
执行上述代码后,您将得到以下结果:
Paulo Coelho
The Alchemist
Paulo Coelho
The Pilgrimage
第一个命令保持原样。在第五遍结束时,两个缓冲区都包含“炼金术士”。在第六遍开始时,它将读取Paulo Coelho行,并且在模式匹配时,不会将该行复制到保持缓冲区中。因此,模式空间包含Paulo Coelho,而容纳空间包含The Alchemist。
此后,它检查模式空间是否包含模式Paulo。模式匹配成功后,它将首先打印模式空间的内容,即Paulo Coelho,然后将保持缓冲区复制到模式缓冲区。因此,模式缓冲区和保持缓冲区都包含The Alchemist。最后,它打印模式缓冲区的内容。相同的步骤应用于“朝圣”模式。
同样,我们可以将保持缓冲区的内容附加到模式缓冲区。 SED提供了G命令,该命令通过在末尾添加新行来将内容附加到模式缓冲区。
[address1[,address2]]G
现在,让我们以前面的示例为例,该示例将作者Paulo Coelhofolol的名字印在书名的后面。要获得相同的结果,请执行以下SED命令。
[jerry]$ sed -n '/Paulo/!h; /Paulo/{G;p}' books.txt
执行上述代码后,您将得到以下结果:
Paulo Coelho
The Alchemist
Paulo Coelho
The Pilgrimage
您可以修改上面的示例以显示其作者之后的书名吗?很简单,只需在G命令之前交换缓冲区内容即可。
[jerry]$ sed -n '/Paulo/!h; /Paulo/{x;G;p}' books.txt
执行上述代码后,您将得到以下结果:
The Alchemist
Paulo Coelho
The Pilgrimage
Paulo Coelho