流编辑器 - 管理模式

我们已经讨论了模式和保持缓冲区的使用.在本章中,我们将探讨有关其用法的更多信息.让我们讨论打印模式空间的 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 命令打印模式缓冲区的内容,清除模式缓冲区,将下一行提取到模式缓冲区,并在其上应用命令.

让我们考虑在 n 之前有三个SED命令,在 n 之后有两个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读取第一行,即A Storm of剑进入模式缓冲区.

  • 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将第一行(即风暴之风)读入模式缓冲区并检查是否它包含图案保罗与否.由于模式匹配不成功,因此将此行复制到保留缓冲区.现在,模式缓冲区和保持缓冲区都包含相同的行,即A Storm of Swords.在第二步中,它检查该行是否包含Paulo模式.由于模式不匹配,它不会做任何事情.

在第二遍中,它将下一行George R. R. Martin读入模式缓冲区并应用相同的步骤.对于接下来的三行,它做同样的事情.在第五遍结束时,两个缓冲区都包含炼金术士.在第六遍开始时,它读取保罗科埃略线,当模式匹配时,它不会将此行复制到保持缓冲区.因此,模式缓冲区包含Paulo Coelho,而保持缓冲区包含The Alchemist.

此后,它会检查模式缓冲区是否包含模式Paulo.当模式匹配成功时,它将模式缓冲区的内容与保持缓冲区进行交换.现在模式缓冲区包含Alchemist,而保持缓冲区包含Paulo Coelho.最后,它打印模式缓冲区的内容.相同的步骤适用于模式The Pilgrimage.

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


第一个命令保持原样.在第五遍结束时,两个缓冲区都包含炼金术士.在第六遍开始时,它读取保罗科埃略线,当模式匹配时,它不会将此行复制到保持缓冲区.因此,模式空间包含Paul Coelho,保持空间包含The Alchemist.

此后,它检查模式空间是否包含模式Paulo.当模式匹配成功时,它首先打印模式空间的内容,即Paulo Coelho,然后将保持缓冲区复制到模式缓冲区.因此,模式和保持缓冲区都包含炼金术士.最后,它打印模式缓冲区的内容.相同的步骤适用于模式The Pilgrimage.

同样,我们可以将保持缓冲区的内容附加到模式缓冲区. SED提供 G 命令,该命令通过在末尾添加新行将内容附加到模式缓冲区.

[address1[,address2]]G


现在我们来看看上一个例子打印了作者Paulo Coelhofollowed的书名.要获得相同的结果,请执行以下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