POSIX风格正则表达式
From:?http://blog.chinaunix.net/space.php?uid=20501242&do=blog&id=1940007
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('[[:<:]]gun[[:>:]]', '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 < strlen($inCardNumber); $i++) {
????? $theAdder = (int) $inCardNumber[$i];
????
????? //使在奇數位的數字加倍
????? if($i % 2) {
??????? $theAdder = $theAdder << 1;
??????? 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標簽替換用[b]和[/b]標簽包含的字符:
$string = 'It is [b]not[/b] a matter of diplomacy.';
echo ereg_replace ('\[b]([^[]*)\[/b]', '<b>\1</b>', $string);
It is <b>not</b> a matter of diplomacy.
eregi_replace( )函數是ereg_replace( )不區分大小寫的形式。它的參數和返回值和ereg_replace( )的相同。
4.9.3.3??拆分
split( )函數使用正則表達式來把字符串拆分為較小的塊,作為一個數組返回。如果出現錯誤,則split()返回false??梢赃x擇要返回多少個小塊:
$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')
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的POSIX风格正则表达式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++和C#的指针小解
- 下一篇: 《给产品经理讲技术》笔记之第三章:开发技