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

转载自:IBM developerWorks 中国网站

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///' 命令时,确实有很大不同,因为规则表达式匹配的整个部分将被目标字符串替换,或,在本例中,被删除。这意味着,上例将把下行:
 <b>This</b> is what <b>I</b> meant. 

变成:

 meant. 

我们要的不是这个,而是:

 This is what I meant. 

幸运的是,有一种简便方法来纠正该问题。我们不输入“'<' 字符后面跟有一些字符并以 '>' 字符结束”的规则表达式,而只需输入一个“'<' 字符后面跟有任意数量非 '>' 字符并以 '>' 字符结束”的规则表达式。这将和最短、而不是最长的可能性匹配。新命令如下:

 $ sed -e 's/<[^>]*>//g' myfile.html 

在上例中,'[^>]' 指定“非 '>'”字符,其后的 '*' 完成该表达式以表示“零或多个非 '>' 字符”。对几个 html 文档测试该命令,将他们管道输出到 "more",然后仔细查看其结果。

更多字符匹配
'[ ]' 规则表达式语法更有一些附加选项。要指定字符范围,只要字符不在第一个或最后一个位置,就能够使用 '-',如下所示:

 '[a-x]*' 

这将匹配零或多个全部为 'a'、'b'、'c'...'v'、'w'、'x' 的字符。另外,能够使用 '[:space:]' 字符类来匹配空格。以下是可用字符类的相当完整的列表:

字符类描述
[:alnum:]字母数字 [a-z A-Z 0-9]
[:alpha:]字母 [a-z A-Z]
[:blank:]空格或制表键
[:cntrl:]任何控制字符
[:digit:]数字 [0-9]
[:graph:]任何可视字符(无空格)
[:lower:]小写 [a-z]
[:print:]非控制字符
[:punct:]标点字符
[:space:]空格
[:upper:]大写 [A-Z]
[:xdigit:]十六进制数字 [0-9 a-f A-F]

尽可能使用字符类是很有利的,因为他们能够更好地适应非英语 locale(包括某些必需的重音字符等等).

高级替换功能
我们已看到如何执行简单甚至有些复杂的直接替换,但是 sed 还能够做更多的事。实际上能够引用匹配规则表达式的部分或全部,并使用这些部分来构造替换字符串。作为示例,假设您正在回复一条消息。下例将在每一行前面加上短语 "ralph said: ":

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!