像其他的编程语言,sed还提供了一个循环和分支工具来控制程序的执行流程。本教程将探讨如何使用sed的循环和分支。
sed循环的工作原理类似于现代编程语言中的goto语句。 sed可以跳转到标记标签的行并继续执行下面提供该标签的剩余命令。
以下是对在sed定义一个标签的语法。在这里,冒号后的名称(:)暗示的标签名称。
:label :start :end :up
要跳转到一个特定的标签,我们可以使用 b 命令后面跟标签名称。如果标签的名称省略,则 sed 跳转到 sed 文件的末尾。
考虑一下我们有一个待处理文本文件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
下面的例子是连接书名,并在一行用逗号分隔作者姓名。然后,它会搜索模式“Paulo”。如果能够匹配,它打印一个连字符(- )在该行的前面,否则跳转到打印行打印标签。
[jerry]$ sed -n ' h;n;H;x s/\n/, / /Paulo/!b Print s/^/- / :Print p' 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
初看起来,上面的脚本可能看起来神秘。让我们看看这是什么情况。
-
最初sed读入模式缓冲区第一行即书名和保持缓冲区保持为空。后执行-h命令模式缓冲区被复制到保留缓冲区。现在,这两个缓冲区包含了本书即标题. A Storm of Swords. 接下来n命令打印当前的模式缓冲区(在本例中没有打印出来,因为-n选项),清除当前图形缓冲区读取输入的下一行。现在模式缓冲区包含George R. R. Martin。
-
第三个命令跳到仅当模式不匹配,否则取代是由第四指令执行的标签Print。
-
:Print 仅仅是一个标签名,p是打印命令。
为了提高可读性,每个sed命令被放置在一个单独的行。然而,人们可以选择将所有命令在一行中,如下所示:
[jerry]$ sed -n 'h;n;H;x;s/\n/, /;/Paulo/!b Print; s/^/- /; :Print;p' 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