1.7 规则表达式(Regular Expressions) |
许多UNIX程序(例如grep, sed和awk[1]), 编辑器(象vi和emacs)和某些shells使用规则表达式(AKA regexps, regexes或REs)。一个表达式是描述一组字符串的一个方法,而不必列出全部字符串。
[1]关于规则表达式概念信息的一个好的原文件是Nutshell Handbook sedand awk, 作者是Dale Dougherty。
在Perl中有多种方法使用规则表达式。首先和最常见的是用在条件中,以确定一个字符串是否匹配一个特别的句型。所以当你看到象/foo/这样的表示时, 你知道你正看到一个普通的匹配句型的操作符。
第二,如果你能在一个字符串内找到一个串,那么你能用另一个串来替代这个串。所以当你看到象s/foo/bar/情况时, 你知道这是请求Perl把foo替代为bar。我们称这是替代操作符(substitution)。
最后,匹配操作不仅能指定哪儿是肯定的,也能指定哪儿是否定的。所以split操作符使用一个规则表达式以指定哪些数据是否定的。即,规则表达式定义分离数据域的下限。班级的例子中有这样的使用。5行和12行为了返回一个词的表按着空字符分离字符串。当你能用一个规则表达式指定分离的下限。 (当匹配字母字符时, 你能在象忽略等情况的上下文中使用各种修饰符)
规则表达式的最简单使用是匹配一个字母表达式。在我们刚提到的分离情况中,我们匹配一个单个的空格。但是如果你匹配一行中的几个字符,他们也都能顺序地匹配。即,句型查找一个你希望的子串。现在,我们想显示和另一些HTML文件(与FTP联结相反)联结的一个HTML文件的所有行。假设我们第一次用HTML做。我们知道这些联结总有"http:"。我们可以用这个循环我们的文件[2]:
[2]这是很类似于UNIX命令"grep 'http:' file"所做的。在MS-DOS中, 你能使用find命令, 但这个不能做更复杂的规则表达式。(但是, Windos NT中的程序findstr知道规则表达式)。
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"匹配, 但从左到右查找,在它发现第一个匹配后就停止查找。
[3]除了它不匹配一个换行符。当你想到它时,在grep(1)中一个"."不匹配一个换行符。
Copyright: NPACT |