另外一個零寬界定符(zero-width assertion)是前向界定符。前向界定符包括前向確定界定符和前項否認界定符,以下所示:正則表達式
(?=...)code
前向確定界定符。若是所含正則表達式,以 ... 表示,在當前位置成功匹配時成功,不然失敗。但一旦所含表達式已經嘗試,匹配引擎根本沒有提升;模式的剩餘部分還要嘗試界定符的右邊。字符串
(?!...)io
前向否認界定符。與確定界定符相反;當所含表達式不能在字符串當前位置匹配時成功class
經過示範在哪前向能夠成功有助於具體實現。考慮一個簡單的模式用於匹配一個文件名,並將其經過 "." 分紅基本名和擴展名兩部分。如在 "news.rc" 中,"news" 是基本名,"rc" 是文件的擴展名。擴展
匹配模式很是簡單:方法
.*[.].*$
注意 "." 須要特殊對待,由於它是一個元字符;我把它放在一個字符類中。另外注意後面的 $; 添加這個是爲了確保字符串全部的剩餘部分必須被包含在擴展名中。這個正則表達式匹配 "foo.bar"、"autoexec.bat"、 "sendmail.cf" 和 "printers.conf"。文件
如今,考慮把問題變得複雜點;若是你想匹配的擴展名不是 "bat" 的文件名?一些不正確的嘗試:sse
.*[.][^b].*$
上面的第一次去除 "bat" 的嘗試是要求擴展名的第一個字符不是 "b"。這是錯誤的,由於該模式也不能匹配 "foo.bar"。mail
.*[.]([^b]..|.[^a].|..[^t])$
當你試着修補第一個解決方法而要求匹配下列狀況之一時表達式更亂了:擴展名的第一個字符不是 "b"; 第二個字符不是 "a";或第三個字符不是 "t"。這樣能夠接受 "foo.bar" 而拒絕 "autoexec.bat",但這要求只能是三個字符的擴展名而不接受兩個字符的擴展名如 "sendmail.cf"。咱們將在努力修補它時再次把該模式變得複雜。
.*[.]([^b].?.?|.[^a]?.?|..?[^t]?)$
在第三次嘗試中,第二和第三個字母都變成可選,爲的是容許匹配比三個字符更短的擴展名,如 "sendmail.cf"。
該模式如今變得很是複雜,這使它很難讀懂。更糟的是,若是問題變化了,你想擴展名不是 "bat" 和 "exe",該模式甚至會變得更復雜和混亂。
前向否認把全部這些裁剪成:
.*[.](?!bat$).*$
前向的意思:若是表達式 bat 在這裏沒有匹配,嘗試模式的其他部分;若是 bat$ 匹配,整個模式將失敗。後面的 $ 被要求是爲了確保象 "sample.batch" 這樣擴展名以 "bat" 開頭的會被容許。
將另外一個文件擴展名排除在外如今也容易;簡單地將其作爲可選項放在界定符中。下面的這個模式將以 "bat" 或 "exe" 結尾的文件名排除在外。
.*[.](?!bat$|exe$).*$