Sed - 管理模式

  • 简述

    我们已经讨论了模式和保持缓冲区的使用。在本章中,我们将更多地探讨它们的用法。让我们讨论一下n打印模式空间的命令。它将与其他命令一起使用。下面给出了 then 命令的语法。
    
    [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 
    
    ncommand 打印模式缓冲区的内容,清除模式缓冲区,获取下一行到模式缓冲区,并在其上应用命令。
    让我们考虑之前有三个 SED 命令n和两个 SED 命令之后n如下:
    
    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 Swords 读入模式缓冲区。
    • 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。由于模式匹配不成功,它将这一行复制到保持缓冲区。现在模式缓冲区和保持缓冲区都包含同一行,即 A Storm of Swords。在第二步中,它检查该行是否包含 Paulo 模式。由于模式不匹配,它不做任何事情。
    在第二遍中,它将下一行 George RR Martin 读入模式缓冲区并应用相同的步骤。对于接下来的三行,它做同样的事情。在第五遍结束时,两个缓冲区都包含 The Alchemist。在第六遍开始时,它读取 Paulo Coelho 行,当模式匹配时,它不会将此行复制到保持缓冲区中。因此,模式缓冲区包含 Paulo Coelho,而保持缓冲区包含 The Alchemist。
    此后,它检查模式缓冲区是否包含模式 Paulo。随着模式匹配成功,它将模式缓冲区的内容与保持缓冲区交换。现在模式缓冲区包含炼金术士,保持缓冲区包含 Paulo Coelho。最后,它打印模式缓冲区的内容。相同的步骤适用于朝圣图案。
    h命令破坏保持缓冲区的先前内容。这并不总是可以接受的,因为有时我们需要保留内容。为此,SED 提供H通过在末尾添加新行将内容附加到保持缓冲区的命令。之间的唯一区别hH命令是,前者覆盖保持缓冲区中的数据,而后者将数据附加到保持缓冲区。它的语法类似于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
    
    第一个命令保持原样。在第五遍结束时,两个缓冲区都包含 The Alchemist。在第六遍开始时,它读取 Paulo Coelho 行,当模式匹配时,它不会将此行复制到保持缓冲区中。因此,模式空间包含 Paulo Coelho,而保持空间包含 The Alchemist。
    此后,它检查模式空间是否包含模式 Paulo。当模式匹配成功时,它首先打印模式空间的内容,即 Paulo Coelho,然后将保持缓冲区复制到模式缓冲区。因此,模式和保持缓冲区都包含炼金术士。最后,它打印模式缓冲区的内容。相同的步骤适用于朝圣图案。
    同样,我们可以将保持缓冲区的内容附加到模式缓冲区。SED 提供G通过在末尾添加新行将内容附加到模式缓冲区的命令。
    
    [address1[,address2]]G
    
    现在让我们以前面的例子为例,它打印出作者 Paulo Coelho 的名字,然后是书名。要获得相同的结果,请执行以下 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