通用线程--sed 实例,第2部分


通用线程 -- sed 实例,第 2 部分
sed 是十分强大和小巧的文本流编辑器 。在本文章系列的第二篇中,DanIEl Robbins 为您演示如何使用 sed 来执行字符串替换、创建更大的 sed 脚本以及如何使用 sed 的附加、插入和更改行命令 。
sed 是很有用(但常被遗忘)的 Unix 流编辑器 。在以批处理方式编辑文件或以有效方式创建 shell 脚本来修改现有文件方面,它是十分理想的工具 。本文是前一篇介绍 sed 文章的续篇 。替换!
让我们看一下 sed 最有用的命令之一,替换命令 。使用该命令,可以将特定字符串或匹配的规则表达式用另一个字符串替换 。下面是该命令最基本用法的示例:$ sed -e "s/foo/bar/" myfile.txt
上面的命令将 myfile.txt 中每行第一次出现的 "foo"(如果有的话)用字符串 "bar" 替换,然后将该文件内容输出到标准输出 。请注意,我说的是每行第一次出现,尽管这通常不是您想要的 。在进行字符串替换时,通常想执行全局替换 。也就是说,要替换每行中的所有出现,如下所示:$ sed -e "s/foo/bar/g" myfile.txt
在最后一个斜杠之后附加的 "g" 选项告诉 sed 执行全局替换 。关于 "s///" 替换命令,还有其它几件要了解的事 。首先,它是一个命令,并且只是一个命令,在所有上例中都没有指定地址 。这意味着,"s///" 还可以与地址一起使用来控制要将命令应用到哪些行,如下所示:$ sed -e "1,10s/enchantment/entrapment/g" myfile2.txt
上例将导致用短语 "entrapment" 替换所有出现的短语 "enchantment",但是只在第一到第十行(包括这两行)上这样做 。$ sed -e "/^$/,/^END/s/hills/mountains/g" myfile3.txt
该例将用 "mountains" 替换 "hills",但是,只从空行开始,到以三个字符 "END" 开始的行结束(包括这两行)的文本块上这样做 。关于 "s///" 命令的另一个妙处是 "/" 分隔符有许多替换选项 。如果正在执行字符串替换,并且规则表达式或替换字符串中有许多斜杠,则可以通过在 "s" 之后指定一个不同的字符来更改分隔符 。例如,下例将把所有出现的 /usr/local 替换成 /usr:$ sed -e "s:/usr/local:/usr:g" mylist.txt
在该例中,使用冒号作为分隔符 。如果需要在规则表达式中指定分隔符字符,可以在它前面加入反斜杠 。规则表达式混乱
目前为止,我们只执行了简单的字符串替换 。虽然这很方便,但是我们还可以匹配规则表达式 。例如,以下 sed 命令将匹配从 "<" 开始、到 ">" 结束、并且在其中包含任意数量字符的短语 。下例将删除该短语(用空字符串替换):$ sed -e "s/<.*>//g" myfile.HTML
这是要从文件除去 HTML 标记的第一个很好的 sed 脚本尝试,但是由于规则表达式的特有规则,它不会很好地工作 。原因何在?当 sed 试图在行中匹配规则表达式时,它要在行中查找最长的匹配 。在我的前一篇 sed 文章中,这不成问题,因为我们使用的是 "d" 和 "p" 命令,这些命令总要删除或打印整行 。但是,在使用 "s///" 命令时,确实有很大不同,因为规则表达式匹配的整个部分将被目标字符串替换,或者,在本例中,被删除 。这意味着,上例将把下行:This is what I meant.
变成:meant.
我们要的不是这个,而是:This is what I meant.
幸运的是,有一种简便方法来纠正该问题 。我们不输入“"<" 字符后面跟有一些字符并以 ">" 字符结束”的规则表达式,而只需输入一个“"<" 字符后面跟有任意数量非 ">" 字符并以 ">" 字符结束”的规则表达式 。这将与最短、而不是最长的可能性匹配 。新命令如下:$ sed -e "s/<[^>]*>//g" myfile.html
在上例中,"[^>]" 指定“非 ">"”字符,其后的 "*" 完成该表达式以表示“零或多个非 ">" 字符” 。对几个 html 文件测试该命令,将它们管道输出到 "more",然后仔细查看其结果 。更多字符匹配

推荐阅读