POSIX风格正则表达式
时间:2007-03-03 来源:lib
4.9 POSIX风格正则表达式
POSIX-Style Regular
Expressions POSIX
你已经了解了正则表达式的基础知识,接下来我们可以讨论一下其细节。POSIX风格的正则表达式使用Unix地区系统(locale system),该系统提供了排序和识别字符的函数来让你智能地处理其他非英语的文本。特别地,各种语言组成单词的”字母”(如 à 和ç)不同,POSIX正则表达式考虑到了这一点并提供相应的字符类。
然而,POSIX正则表达式是为使用仅有原文的数据而设计的。如果数据中有空字节(\x00),那么正则表达式函数把它理解为字符串的末尾,并且匹配不会超过该字节位置。要匹配任意的二进制数据,需要使用本章稍后讨论的兼容Perl的正则表达式。正如我们已经提到的,Perl风格的正则表达式函数常常比等效的POSIX风格的函数快。
4.9.1 字符类
Character
Classes
如表4-7所示,POSIX定义了许多可以在字符类中使用的命名字符集。在表4-7中给出的扩展是英语的。实际的字母根据使用者地区(locale)不同而不同。 译注1
表4-7:POSIX字符集
类
描 述
扩 展
[:alnum:]
字母和数字字符
[0-9a-zA-Z]
[:alpha:]
(letters)字母字符(字母)
[a-zA-Z]
[:ascii:]
7位ASCII
[\x01-\x7F]
[:blank:]
水平空白符(空格、制表符)
[ \t]
[:cntrl:]
控制字符
[\x01-\x1F]
[:digit:]
数字
[0-9]
[:graph:]
用墨水打印的字符(非空格、非控制字符)
[^\x01-\x20]
[:lower:]
小写字母
[a-z]
[:print:]
可打印字符(图形类加空格和制表符)
[\t\x20-\xFF]
[:punct:]
任意标点符号,如句点(.)和分号(;)
[-!"#$%&'(
)*+,./:;?@[\\\]^_'{|}~]
[:space:]
空白(换行、回车、制表符、空格、垂直制表符)
[\n\r\t \x0B]
[:upper:]
大写字母
[A-Z]
[:xdigit:]
十六进制数字
[0-9a-fA-F]
每一个[:something:]类都可被用于替代一个字符类中的字符。例如,要查找任一数字字符、大写字母或一个@ 符号,可以使用下面的正则表达式:
[@[:digit:][:upper:]]
但是,不能把一个字符类当作一个范围的终点使用:
ereg('[A-[:lower:]]',
'string'); //非法的正则表达式
一些地区把某些字符序列当作一个单独的字符来考虑——它们被称为排序序列(collating sequence)。在字符类中匹配这些多字符序列中的一个时,要把它用[. 和 .]括起来。
例如,如果你的地区有排序序列ch,你可以使用下面的字符类来匹配s、t或ch:
[st[.ch.]]
POSIX最后的字符类扩展是等价类(equivalence class),把字符用[= 和 =]括起来指定。等价字符类匹配有相同整理顺序的字符(由当前locale定义)。例如,一个地区可能定义a、á和 ä有相同的排序优先级。要匹配它们中的一个,等价类为[=a=]。
4.9.2 锚
Anchors
锚(anchor) 将匹配限制在字符串中特定位置(锚不匹配目标字符串中的实际字符)。表4-8列出了POSIX正则表达式支持的锚。
表4-8:POSIX锚
锚
匹 配
^
字符串开始
$
字符串末尾
[[:
单词开始
[[:>:]]
单词末尾
单词边界指在一个空白符和一个标识符(字母数组或下划线)之间的那一点:
ereg('[[::]]', 'the Burgundy
exploded'); //返回false
ereg('gun', 'the Burgundy
exploded');
//返回true
注意字符串的开头和结尾也可以作为单词边界。
4.9.3 函数
Functions
POSIX风格的正则表达式有三类函数:匹配、替换和拆分。
4.9.3.1 匹配
ereg( )函数接收一个模式、一个字符串和一个可选的数组。如果给定数组的话就组装数组,并根据是否在字符串中找到模式的一个匹配而返回true或false。
$found = ereg(pattern, string [, captured
]);
例如:
ereg('y.*e$', 'Sylvie'); //返回true
ereg('y(.*)e$', 'Sylvie', $a); // 回true,$a是array('Sylvie', 'lvi')
数组的第零个元素设置为与之匹配的整个字符串。第一个元素是与第一个子模式匹配的子字符串,第二个元素是与第二个子模式匹配的子字符串,依此类推。
eregi( )函数是不区分大小写的ereg( )。它的参数和返回值都和ereg( )相同。
示例4-1使用模式匹配来确定一个信用卡号是否通过了Luhn校验,以及该数字是否符合特定的信用卡格式。
示例4-1:信用卡验证
// Luhn校验可以判断一个信用卡号是否遵循正确的校验;但是它不能告知该卡号是否已经//发行、当前是否为活动的或有足够的空间来存入金额。
function IsValidCreditCard($inCardNumber,
$inCardType) {
//假设是正确的
$isValid = true;
//从字符串中删除所有非数字字符
$inCardNumber =
ereg_replace('[^[:digit:]]','', $inCardNumber);
//确认卡号和类型匹配
switch($inCardType) {
case 'mastercard':
$isValid =
ereg('^5[1-5].{14}$', $inCardNumber);
break;
case 'visa':
$isValid =
ereg('^4.{15}$|^4.{12}$', $inCardNumber);
break;
case 'amex':
$isValid =
ereg('^3[47].{13}$', $inCardNumber);
break;
case 'discover':
$isValid =
ereg('^6011.{12}$', $inCardNumber);
break;
case 'diners':
$isValid =
ereg('^30[0-5].{11}$|^3[68].{12}$', $inCardNumber);
break;
case 'jcb':
$isValid =
ereg('^3.{15}$|^2131|1800.{11}$', $inCardNumber);
break;
}
//通过了基本的测试,现在进行Luhn校验
if($isValid) {
//翻转
$inCardNumber =
strrev($inCardNumber);
//合计数字的总位数,在奇数位加倍
$theTotal = 0;
for ($i = 0; $i $theAdder = (int)
$inCardNumber[$i];
//使在奇数位的数字加倍
if($i % 2) {
$theAdder = $theAdder
if($theAdder > 9) { $theAdder -= 9; }
}
$theTotal +=
$theAdder;
}
//合法的卡号除以10
$isValid = (($theTotal % 10) ==
0);
}
return $isValid;
}
4.9.3.2 替换
ereg_replace( )函数的参数为一个模式、一个替换字符串和一个要在其中进行查找的字符串。函数返回查找字符串的一个拷贝,字符串中与模式匹配的文本用替换字符串来代替。
$changed = ereg_replace(pattern, replacement,
string);
如果该模式有任何分组的子模式,则该匹配可以通过把字符\1到\9放到替换字符串中来访问。例如,可以使用ereg_replace()以等价的HTML标签替换用和标签包含的字符:
$string = 'It is not a matter of
diplomacy.';
echo ereg_replace ('\([^[]*)\',
'\1', $string);
It is not a matter of
diplomacy.
eregi_replace( )函数是ereg_replace( )不区分大小写的形式。它的参数和返回值和ereg_replace( )的相同。
4.9.3.3 拆分
split( )函数使用正则表达式来把字符串拆分为较小的块,作为一个数组返回。如果出现错误,则split()返回false。可以选择要返回多少个小块:
$chunks = split(pattern, string [,
limit ]);
本函数的模式用于匹配分隔成块的文本。例如,从一个算术表达式中拆分项:
$expression = '3*5+i/6-12';
$terms = split('[/+*-]', $expression);
// $terms 是
array('3', '5', 'i', '6', '12')
如果指定了一个匹配数目限制,则数组的最后一个元素会存放剩余的字符串:
$expression = '3*5+i/6-12';
$terms = split('[/+*-]', $expression, 3);
// $terms 是 array('3', '5', 'i/6-12')
相关阅读 更多 +
排行榜 更多 +