Sed 是一个 流编辑器。一些 developerWorks 文章以及众多书籍和图书章节都介绍了 sed。Sed 的功能极其强大,对它的唯一限制也许就是您的想象力。下面的简单介绍将唤起您对 sed 的兴趣,但是这里并不打算给出全面或详细的介绍。
如同我们目前已经了解的许多文本命令一样,seb 可以充当一个过滤器,或者从文件中获取其输入。输出将被放入到标准输出流。sed 将输出中的行加载到模式空间(pattern space),对模式空间的内容应用 sed 编辑命令,然后将模式空间写入到标准输出中。Sed 可以在模式空间中组合多个行,然后它可能将输出写入到文件中、只写入选择的输出,或者根本不执行写入。
Sed 使用正则表达式语法在模式空间中搜索并有选择地替换文本,以及决定对哪些文本行应用编辑命令。我们将在有关使用正则表达式搜索文本文件 的文章中更详细地介绍正则表达式(可以在 学习 Linux,101: LPIC-1 路线图 中找到)。保持缓存 为文本提供了临时存储。保持缓存可以取代模式空间、被添加到模式空间,或者与模式空间进行互换。Sed 提供了一组有限的命令,但是这些命令结合了正则表达式语法和保持缓存,因而实现了某些非常令人吃惊的功能。sed 命令集常常被称为 sed 脚本。
清单 20 展示了三个简单的 sed 脚本。在第一个脚本中,我们使用 s(替换)命令来将每一行中的小写 ‘a’ 替换为大写。这个例子仅替换了第一个 ‘a’,因此在第二个例子中,我们添加了 ‘g’(表示全局)标记,以使 sed 替换出现的所有小写 ‘a’。在第三个脚本中,我们引入 d(删除)命令来删除某行。在我们的例子中,我们使用地址 2 来表示只删除第 2 行。我们使用分号(;)分隔命令,并使用第二个脚本中用到的全局替换来将 ‘a’ 替换为 ‘A’。
清单 20. sed 脚本
[ian@echidna lpi103-2]$ sed 's/a/A/' text1 1 Apple 2 peAr 3 bAnana [ian@echidna lpi103-2]$ sed 's/a/A/g' text1 1 Apple 2 peAr 3 bAnAnA [ian@echidna lpi103-2]$ sed '2d;$s/a/A/g' text1 1 apple 3 bAnAnA
除了操作单独的行外,sed 还可以操作一个行范围。行的起始和结束由一个逗号(,)分隔,并且可以被指定为行号、正则表达式或表示文件结束的美元符号($)。对于一个地址或一个地址范围,可以在大括号 { 和 } 之间对命令进行分组,使这些命令只用于按范围选择的行。清单 21 展示了对文件的最后两行应用全局替代的两种方式。它还演示了使用 -e 选项向脚本添加多个命令。
清单 21. Sed 地址
[ian@echidna lpi103-2]$ sed -e '2,${' -e 's/a/A/g' -e '}' text1 1 apple 2 peAr 3 bAnAnA [ian@echidna lpi103-2]$ sed -e '/pear/,/bana/{' -e 's/a/A/g' -e '}' text1 1 apple 2 peAr 3 bAnAnA
Sed 脚本也可以存储到文件中。事实上,您很可能希望对经常使用的脚本执行这个操作。回忆一下,我们前面使用 tr 命令将 text1 中的空格修改为制表符。现在让我们使用存储在文件中的 sed 脚本来实现相同的操作。我们将使用 echo 命令来创建文件。结果如清单 22 所示。
清单 22. sed 单行脚本
[ian@echidna lpi103-2]$ echo -e "s/ /\t/g">sedtab [ian@echidna lpi103-2]$ cat sedtab s/ / /g [ian@echidna lpi103-2]$ sed -f sedtab text1 1 apple 2 pear 3 banana
还有许多像清单 22 这样方便的 sed 单行脚本。
最后一个 sed 示例使用 = 命令输出行号,然后再次使用 sed 过滤生成的输出,以模拟使用 nl 命令对行进行编号的效果。清单 23 使用 = 输出行号,然后使用 N 命令将第二个输入行读取到模式空间,最后删除模式空间中两个行之间的换行符(\n)。