有个问题我们一直没讨论到:有多少文本会匹配 ?事实上,这应该包含两个问题。第二个问题:从哪开始匹配?执行简单的文本查找,例如使用 grep 或 egrep 时,则这两个问题都不重要,你只要知道是否有一行是匹配的,若有,则看看那一行是什么。至于在这个行里,是从哪儿开始匹配,或者它扩展到哪里,已经不重要了。
但如果你要使用 sed 执行文本替换,或者要用 awk 写程序,这两个问题的打哪就变得非常重要了(如果你每天都在文本编辑器内工作,这也算是个重要议题,只是本书的重点不在文本编辑器)。
这两个问题的答案是:正则表达式匹配可以匹配整个表达式的输入文本中最长的、最左边的子字符串。除此之外,匹配的空(null)字符串,则被认为是比完全不匹配的还长(因此,就像我们先前所解释的,正则表达式:ab*c匹配文本 ac ,而 b* 则成功地匹配于 a 与 c 之间的 null 字符串)。再者,POSIX 标准指出:“完全一致的匹配,指的是自最左边开始匹配、针对每一个子模式、由左至右,必须匹配到最长的可能字符串”。(子模式指的是在 ERE 下圆括号里的部分。为此目的,GNU 的程序通常也会在 BRE 里以 ( ... ) 提供此功能)。
如果 sed 要替代由正则表达式匹配的文本,那么确定该正则表达式匹配的字不会太少或太多就非常重要了。这里有个简单例子:
[many@avention Desktop]$ echo Tolstoy writes well | sed 's/Tolstoy/Camus/' #使用固定字符串
Camus writes well
当然,sed 可以使用完整的正则表达式。这里就是要告诉你,了解“从最长的最左边(longest leftmost)”规则有多的重要:
[many@avention Desktop]$ echo Tolstoy is worldly | sed 's/T.*y/Camus/' #试试正则表达式
Camus #结果呢?
很明显,这里只是要匹配 Tolstoy ,但由于匹配会扩展到可能的最长长度的文本量,所以就一直找到 worldly 的 y 了!你需要定义的更精确些:
[many@avention Desktop]$ echo Tolstoy is worldly | sed 's/T[[:alpha:]]*y/Camus/'
Camus is worldly
通常,当开发的脚本是要执行大量文本剪贴和排列组合时,你会希望谨慎地测试每样东西,确认每个步骤都是你要的 -- 尤其是当你在学习正则表达式里的微妙变化的阶段的时候。
最后,正如我们所见的,在文本查找时有可能会匹配到 null 字符串。而在执行文本替代时,也允许你插入文本:
[many@avention Desktop]$ echo abc | sed 's/b*/1/' #替代第一个匹配成功的
1abc
[many@avention Desktop]$ echo abc | sed 's/b*/1/g' #替代所有匹配成功的
1a1c1
请留意,b* 是如何匹配在 abc 的前面与结尾的 null 字符串。