1.7 规则表达式(Regular Expressions) BACKWARDFORWARD


许多UNIX程序(例如grep, sed和awk[1]), 编辑器(象vi和emacs)和某些shells使用规则表达式(AKA regexps, regexes或REs)。一个表达式是描述一组字符串的一个方法,而不必列出全部字符串。

在Perl中有多种方法使用规则表达式。首先和最常见的是用在条件中,以确定一个字符串是否匹配一个特别的句型。所以当你看到象/foo/这样的表示时, 你知道你正看到一个普通的匹配句型的操作符。

第二,如果你能在一个字符串内找到一个串,那么你能用另一个串来替代这个串。所以当你看到象s/foo/bar/情况时, 你知道这是请求Perl把foo替代为bar。我们称这是替代操作符(substitution)。

最后,匹配操作不仅能指定哪儿是肯定的,也能指定哪儿是否定的。所以split操作符使用一个规则表达式以指定哪些数据是否定的。即,规则表达式定义分离数据域的下限。班级的例子中有这样的使用。5行和12行为了返回一个词的表按着空字符分离字符串。当你能用一个规则表达式指定分离的下限。 (当匹配字母字符时, 你能在象忽略等情况的上下文中使用各种修饰符)

规则表达式的最简单使用是匹配一个字母表达式。在我们刚提到的分离情况中,我们匹配一个单个的空格。但是如果你匹配一行中的几个字符,他们也都能顺序地匹配。即,句型查找一个你希望的子串。现在,我们想显示和另一些HTML文件(与FTP联结相反)联结的一个HTML文件的所有行。假设我们第一次用HTML做。我们知道这些联结总有"http:"。我们可以用这个循环我们的文件[2]:

while ($line = <FILE>)

  if ($line =~ /http:/)

   print $line;

这儿, =~(句型联结操作符)是告诉Perl在变量$line中查找规则表达式http:。如果它发现这个表达式就返回一个真值, 并执行block(一个print命令)。如果你不使用=~联结操作符, 那么Perl将查找一个缺省句型空间而不是$line。这个缺省空间就是一个特别的变量,名字为$_。事实上,Perl中的许多操作符缺省使用$_变量, 所以, Perl的编程专家这样写上面的程序:

while (<FILE>)

  print if /http:/;

这个程序是很方便的, 但如果我们想找到所有的link, 不只是HTTP, 怎么办? 我们可以给出link的一个表, 象"http:", "ftp:", "mailto:" 等等。但这个表较长,当一个新的link加入时, 我们将怎样做?

while (<FILE>)

  print if /http:/;

  print if /ftp:/;

  print if /mailto:/;

  #下一个

因为规则表达式是一组字符串的描述, 所以我们能描述我们所查找的: 一些字母字符后有一个冒号。在规则表达式中应是/[a-zA-Z]+:/, 这儿方括号定义一个字符类。a-z和A-Z表示所有的字母字符( '-'意思是在开始和结束字符之间的所有字符的范围 )。'+'是一个特殊的字符, 意思是"有一个或多个它前面的符号"。这就是我们所说的数量词,意思是某件事重复的次数。(//不是规则表达式的部分, 但是匹配操作符的一部分。//象引号一样, 出现在包含一个规则表达式的地方)。

因为象字母一类是如此常用,Perl为他们定义一种特殊情况。这些特殊情况包括:


表1-7: 规则表达式字符类


名字        定义     字符

空格(whitespace)  [\t\n\r\f]   \s

字符(word)     [a-zA-Z0-9]  \w

数字(digit)     [0-9]      \d

注意这些匹配单个字母。一个将匹配任何单个字母, 而不是整个词。(记得+数量词吗? 为匹配一个词, 你可以说+)。通过使用大写字母,Perl提供这些的相反表示, 例如表示非数字字符。

(我们将注意到不总是等价于[a-zA-Z0-9]。有些地方定义ASCII以外的附加字母字符, 代表他们。)

有一种很特殊的字符类,用"."书写, 它将匹配任何字符[3]。例如,/a./将匹配任何包含"a"的一个字符串, a不是这个串的最后一个字符。所以,将匹配"at", "am" 或 "a+", 但不是"a", 因为在"a"之后没有和点(.)匹配的字符。因为它在字符串的任何地方查找这个句型,它将匹配"oasis"和"camel",但不匹配"sheba"。它在第一个"a"匹配"caravan"。它能在第二个"a"匹配, 但从左到右查找,在它发现第一个匹配后就停止查找。


Copyright: NPACT BACKWARDFORWARD