[TOC]
## 基本的元字符
| 元字符 | 說明 |
| --- | --- |
| `.` | 匹配任意單個字符 |
| `|` | 邏輯或操作符 |
| `[]` | 匹配字符集合中的一個字符 |
| `[^]` | 對字符集合求非 |
| `-` | 定義一個區間(例如[A-Z]) |
| `\` | 對下一個字符轉義 |
## 數量元字符
| 元字符 | 說明 |
| --- | --- |
| `*` | 匹配前一個字符(子表達式)的0次或多次重復 |
| `*?` | `*`的懶惰型版本 |
| `+` | 匹配前一個字符(子表達式)的1次或多次重復 |
| `+?` | `+`的懶惰型版本 |
| `?` | 匹配前一個字符(子表達式)的0次或1次重復 |
| `{n}` | 匹配前一個字符(子表達式)的n次重復 |
| `{m,n}` | 匹配前一個字符(子表達式)至少m次且至多n次重復 |
| `{n,}` | 匹配前一個字符(子表達式)n次或更多次重復 |
| `{n,}?` | `{n,}`的懶惰型版本 |
| 貪婪型元字符 | 懶惰型元字符 |
| --- | --- |
| `*` | `*?` |
| `+` | `+?` |
| `{n,}` | `{n,}?` |
在需要防止過度匹配的場合下,使用“懶惰型”元字符來構造正則表達式。
## 位置元字符
| 元字符 | 說明 |
| --- | --- |
| `^` | 匹配字符串的開頭 |
| `\A` | 匹配字符串的開頭 |
| `$` | 匹配字符串的結束 |
| `\Z` | 匹配字符串的結束 |
| `\<` | 匹配單詞的開頭 |
| `\>` | 匹配單詞的結束 |
| `\b` | 匹配單詞邊界(開頭和結束) |
| `\B` | `\b`的反義 |
## 特殊字符元字符
| 元字符 | 說明 |
| --- | --- |
| `\b` | 退格字符 |
| `\c` | 匹配一個控制字符 |
| `\d` | 匹配一個任意數字字符 |
| `\D` | `\d`的反義 |
| `\f` | 換頁符 |
| `\n` | 換行符 |
| `\r` | 回車符 |
| `\s` | 匹配一個空白字符 == `[\f\n\r\t\v]` |
| `\S` | `\s`的反義 == `[^\f\n\r\t\v]` |
| `\t` | 制表符(Tab字符) |
| `\v` | 垂直制表符 |
| `\w` | 匹配一個任意字母、數字和下劃線字符 == `[a-zA-z0-9_]` |
| `\W` | `\w`的反義 == `[^a-zA-z0-9_]` |
| `\x` | 匹配一個十六進制數字 |
| `\0` | 匹配一個八進制數字 |
舉例:
1. `\x0A` == `\n`
`\x0A`對應于ASCII字符10(換行符)
2. `\011` == `\t`
`\011`對應于ASCII字符9(制表符)
## 回溯引用和前后查找
| 元字符 | 說明 | 舉例 |
| --- | --- |--- |
| `()` | 定義一個子表達式 | (pattern):匹配 pattern 并獲取這一匹配。 |
| `\1` | 匹配第一個子表達式; | |
| `\2` | 匹配第二個子表達式,依次類推 | |
| `?=` | 向前查找 | (?=pattern)正向肯定預查(look ahead positive assert):在任何匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如,`Windows(?=95|98|NT|2000)`能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始。 |
| `?<=` | 向后前查找 | (?<=pattern)反向(look behind)肯定預查,與正向肯定預查類似,只是方向相反。例如,`(?<=95|98|NT|2000)Windows`能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。 |
| `?!` | 負向前查找 | (?!pattern)正向否定預查(negative assert):在任何不匹配pattern的字符串開始處匹配查找字符串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以后使用。例如`Windows(?!95|98|NT|2000)`能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。預查不消耗字符,也就是說,在一個匹配發生后,在最后一次匹配之后立即開始下一次匹配的搜索,而不是從包含預查的字符之后開始。 |
| `?<!` | 負向后查找 | (?<!pattern)反向否定預查,與正向否定預查類似,只是方向相反。例如`(?<!95|98|NT|2000)Windows`能匹配"3.1Windows"中的"Windows",但不能匹配"2000Windows"中的"Windows"。 |
| `?()` | 條件(if then) | |
| `?()|` | 條件(if then else) | |
| `?:` | -- | (?:pattern):匹配 pattern 但不獲取匹配結果,也就是說這是一個非獲取匹配,不進行存儲供以后使用。這在使用 "或" 字符`| `來組合一個模式的各個部分是很有用。例如, `industr(?:y|ies)` 就是一個比 `industry|industries`更簡略的表達式。 |
所獲取的匹配可以從產生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中則使用 $0…$9 屬性。要匹配圓括號字符,請使用 '\(' 或 '\)'。
## 大小寫轉換
| 元字符 | 說明 |
| --- | --- |
| `\E` | 結束`\L`或`\U`轉換 |
| `\l` | 將下一個字符轉為小寫 |
| `\L` | 把后面的字符全轉換為小寫,直到遇到`\E`為止 |
| `\u` | 將下一個字符轉為大寫 |
| `\U` | 把后面的字符全轉換為大寫,直到遇到`\E`為止 |
## 匹配模式
| 元字符 | 說明 |
| --- | --- |
| `?m` | 分行匹配模式 |
## POSIX字符類
| 字符類 | 說明 |
| --- | --- |
| `[:alnum:]` | 任何一個字母或數字(等價于`[a-zA-Z0-9]`) |
| `[:alpha:]` | 任何一個字母(等價于`[a-zA-Z]`) |
| `[:blank:]` | 空格或制表符(等價于`[\t ]`,字母t后是空格) |
| `[:cntrl:]` | ASCII控制字符(ASCII0到31,再加上ASCII 127) |
| `[:digit:]` | 任何一個數字(等價于`[0-9]`) |
| `[:graph:]` | 和`[:print:]`一樣,但不包括空格 |
| `[:lower:]` | 任何一個小寫字母(等價于`[a-z]`) |
| `[:print:]` | 任何一個可打印字符 |
| `[:punct:]` | 既不屬于`[:alnum:]`也不屬于`[:cntrl:]`的任何一個字符 |
| `[:space:]` | 任何一個空白字符,包括空格(等價于`[f\n\r\t\v ]`,字母v后是空格) |
| `[:upper:]` | 任何一個大寫字母(等價于`[A-Z]`) |
| `[:xdigit:]` | 任何一個十六進制數字(等價于`[a-fA-F0-9]`) |
POSIX語法與我們此前見過的元字符不太一樣。為了演示POSIX字符類的用法,我們來看一個例子:利用正則表達式從一段HTML代碼里把RGB值查找出來:
* **文本**
<BODY BGCOLOR="#336633" TEXT="#FFFFFF"
MARGINWIDTH="0" MARGINHEIGHT="0"
TOPMARGIN="0" LEFTMARGIN="0">
* **正則表達式**
`#[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]l[[:xdigit:]][[:xdigit:]]`
* **結果**
~~~
<BODY BGCOLOR="#336633" TEXT="#FFFFFF"
MARGINWIDTH="0" MARGINHEIGHT="0"
TOPMARGIN="0"LEFTMARGIN="0">
~~~
* **分析**
在前一章里使用的模式是重復寫出的6個`[0-9A-Fz-f]`字符集合,把那6個`[0-9A-Fz-f]`全部替換為`[[:xdigit:]]`就得到這里的模式。 它們的
匹配結果完全一樣。
>[info] 這里使用的模式以`[[`開頭,以`]]`結束(兩對方括號)。這是使用POSIX字符類所必須的。POSIX字符類必須括在`[:`和`:]`之間,我們使用的POSIX字符類是`[:xdigit:]`(不是`:xdigit:`)。外層的`[`和`]`字符用來定義一個字符集合,內層的`[`和`]`字符是POSIX字符類本身的組成部分。
## 常見軟件和編程語言中的正則表達式
### grep
grep是一種用來對文件或標準輸入文本進行文字搜索的Unix工具。根據你具體使用的命令選項,grep支持基本、擴展和Perl正則表達式。
* `-E`:使用擴展正則表達式。
* `-G`:使用基本正則表達式。
* `-P`:使用Perl正則表達式。
注意:
* 在默認的情況下,grep將把包含著匹配的各個文本行全部顯示出來;如果你只想查看匹配結果,請使用`-o`選項。
* 使用`-v`選項將對整個匹配操作進行求非一只顯示不匹配的文本行。
* 使用`-c`選項將只顯示匹配的總數而不是此次匹配的細節。
* grep工具只能用來進行搜索操作,不能用來進行替換操作。 即是grep工具不支持替換功能。
### JavaScript
JavaScript 1.x版本在`String`和`RegExp`對象的以下幾個方法里實現了正則表達式處理。
* `exec`:一個用來搜索一個匹配的RegExp方法。
* `match`:一個用來匹配一個字符串的string方法。
* `replace`:一個用來完成替換操作的string方法。
* `search`:一個用來測試在某給定字符串里是否存在著一個匹配的String方法。
* `split`:一個用來把一個字符串拆分為多個子串的String方法。
* `test`:一個用來測試在某給定字符串里是否存在著一個匹配的RegExp方法。
JavaScript 2里的正則表達式處理(Mozilla和另外幾種比較新的瀏覽器可以支持)與JavaScript 1.x向后兼容并提供了更多的功能。
JavaScript對正則表達式的支持源自Perl語言,但需要注意以下幾個問題:
* JavaScript使用命令行選項來管理全局的區分大小寫搜索:`g`選項激活全局搜索功能,`i`選項讓匹配操作不區分字母的大小寫,這兩個選項可以組合為`gi`。
* 其他命令行選項(版本4及以后的瀏覽器支持)包括:`m`,支持多行字符串;`s`,支持單行字符串;`x`,忽略正則表達式模式里的空白字符。
* 在使用回溯引用的時候,`$'`(單引號)將返回被匹配字符串前面的所有東西,$\`\(反引號)將返回被匹配字符串后面的所有東西,`$+`將返回最后一個被匹配的子表達式,`$&`將返回被匹配到的所有東西。
* JavaScript提供了一個名為`RegExp`的全局對象,在執行完一個正則表達式之后,你們可以通過這個對象獲得與這次執行有關的信息。
* JavaScript不支持POSIX字符類。
* JavaScript不支持`\A`和`\Z`.
### PHP
PHP通過它的PCRE組件提供了與Perl相兼容的正則表達式支持。從PHP 4.2.0版本開始,PCRE組件將自動安裝。
下面是PCRE組件提供的一些正則表達式函數:
* `preg_grep()`:進行一次搜索,匹配結果將作為數組返回。
* `preg_match()`:進行一次正則表達式搜索,返回第一個匹配。
* `preg_match_all()`:進行一次正則表達式搜索,返回所有的匹配。
* `preg_quote()`:這個函數的輸入參數是一個模式,返回值是該模式的轉義版本。
* `preg_replace()`:進行一次“搜索并替換”操作。
* `preg_replace_callback()`:進行一次“搜索并替換”操作,但使用一個回調(callback)函數來完成實際替換動作。
* `preg_split()`:把一個字符串拆分為子字符串。
注意:
* 在默認的情況下,匹配操作不區分字母的大小寫。 如果不想區分字母的大小寫,必須使用`i`限定符。
* 在默認的情況下,匹配操作僅限于單行字符串。 如果需要匹配多行字符串,必須使用`m`限定符。
* `preg_replace()`,`preg_replace_callback()`和`preg_split()`函數都支持一個可選的參數,該參數用來給出一個上限值一對字符串進行替換或拆分的最大次數。
* `preg_grep()`和`preg_replace_callback()`是從PHP 4才開始有的,其他函數都是從PHP3開始就被支持的。
* 在PHP4.0.4和更高版本里,回溯引用可以用Perl語言的$語法(例如`$1`)來引用;在較早的版本里必須用`\\`來代替`$`。
* 不支持`\l`,`\u`,`\L`,`\U`,`\Q`和`\v`.
### MySQL
MySQL是一個流行的開放源代碼數據庫軟件。MySQL率先提供了正則表達式支持作為一種數據庫搜索手段, 這一點我們在其他數據庫系統里還沒有見過。
MySQL對正則表達式的支持體現在允許在WHERE子句里使用如下格式的表達式:
~~~
SELECT*FROM table WHERE REGEXP "pattern"
~~~
MySQL正則表達式支持很有用,功能也很強大,但它還算不上是一個完備的正則表達式實現。
* 只提供了搜索支持, 不支持使用正則表達式進行替換操作。
* 在默認的情況下,正則表達式搜索不區分字母的大小寫。 如果需要區分字母的大小寫,必須再增加一個`BINARY`關鍵字(放在`REGEXP`和模式之間).
* 用`[[:<:]]`來匹配一個單詞的開頭,用`[[:>:]]`來匹配一個單詞的結束。
* 不支持向前預測。
* 不支持嵌入條件。
* 不支持八進制字符搜索。
* 不支持`\a`,`\b`,`\e`,`\f`和`\v`.
* 不支持回溯引用。
### Perl
Perl可以說是各種正則表達式實現的“祖宗”,其他各種實現幾乎都與Perl相兼容。
正則表達式支持是Perl的核心組件之一。 如果需要在Perl腳本里使用正則表達式,只要像下面這樣給出一個操作和相應的模式即可。
* `m/pattern/` 匹配給定的模式.
* `s/pattern/pattern/`執行一個替換操作。
* `qr/pattern/`返回一個Regex對象供今后使用。
* `split()`把一個字符串拆分為子字符串。
下面是一些與Perl正則表達式有關的注意事項。
* 允許把限定符放在模式的后面。 `\i`用來表明在搜索時不區分字母的大小寫; `\g`用來表明進行全局搜索(把所有的匹配都找出來)。
* 在使用“回溯引用”的時候,`$'`將返回被匹配字符串前面的所有東西,$`將返回被匹配字符串后面的所有東西,`$+`將返回最后一個被匹配的子表達式,`$&`將返回整個被匹配字符串。
### Java
Java對正則表達式的支持是從1.4版本開始的,此前的JRE(JavaRuntime Environment,Java運行壞境)版本不支持正則表達式。
>[danger] 版本低于1.4的JRE現在仍被廣泛地使用著。 如果你打算部署一個使用了正則表達式的Java應用程序,千萬不要忘記檢查JRE的版本。
Java語言中的正則表達式匹配功能主要是通過`java.util.regex.Matcher`類和以下這些方法實現的。
* `find()`:在一個字符串里尋找一個給定模式的匹配。
* `lookingAt()`:用一個給定的模式去嘗試匹配一個字符串的開頭。
* `matches()`:用一個給定的模式去嘗試匹配一個完整的字符串。
* `replaceAll()`:進行替換操作,對所有的匹配都進行替換。
* `replaceFirst()`:進行替換操作,只對第一個匹配進行替換。
Matcher類還提供了幾個能夠讓程序員對特定操作做出更細致調控的方法。此外,`java.util.regex.Pattern`類也提供了幾個簡單易用的包裝器方法:
* `compile()`:把一個正則表達式編譯成一個模式。
* `flags()`:返回某給定模式的匹配標志。
* `matches()`:在功能上等價于剛才介紹的`matches()`方法。
* `pattern()`:把一個模式還原為一個正則表達式。
* `split()`:把一個字符串拆分為子字符串。
Sun公司發布的Java正則表達式支持與Perl語言基本兼容,但要注意以下幾點。
* 要想使用正則表達式,必須先用`import java.util.regex.*`語句導入正則表達式組件(這條語句將導入一個完整的軟件包。 如果你只需要用到其中的一部分功能, 請用相應的軟件包名字替換掉
這條語句里的*)。
* 不支持嵌入條件.
* 不支持使用`\E`、`\l`,`\L`,`\u`和`\U`進行字母大小寫轉換。
* 不支持使用`[\b]`匹配退格符.
* 不支持`\z`。
## 應用舉例
### 北美電話號碼
北美地區(美國、加拿大、加勒比海地區大部以及其他幾個地區)的電話號碼
1. 由一個3位數的區號和一個7位數的號碼構成
2. 這7位數字又分成一個3位數的局號和一個4位數的線路號,局號和線路號之間用連字符(`-`)或小數點(`.`)分隔
3. 每位電話號碼可以是任意數字,但區號和局號的第一位數字不能是0或1
4. 在書寫電話號碼的時候,人們往往把區號放在括號里,而且還往往會在區號與實際電話號碼之間加上一個連字符(`-`)或小數點(`.`)來分隔它們。
* **文本**
J.Doe: 248-555-1234
B.Smith:(313) 555-1234
A.Lee: (810)555-1234
M.Jones: 734.555.9999
* **正則表達式**
`[\(.]?[2-9]\d\d[\).]?[ -]?[2-9]\d\d[-.]\d{4}`
* **結果**
J.Doe: `248-555-1234`
B.Smith: `(313) 555-1234`
A.Lee: `(810)555-1234`
M.Jones: `734.555.9999`
### 中國固定電話號碼
1. 區號。以數字0開頭的3~5位的號碼
2. 電話號碼。以不為1開頭的7~8位號碼
* **文本**
029 88457890
029 8845 7890
(029) 8845 7890
(029) 88457890
029-88457890
029-8845 7890
029-8845-7890
* **正則表達式**
`\(?0[1-9]\d{1,3}\)?[-]?[2-9]\d{2,3}[-]\d{4}`
### 美國郵政編碼(ZIP)
ZIP: Zone Improvement Plan
ZIP編碼規則
1. 5位數字的ZIP編碼
2. 9位數字的ZIP+4編碼(ZIP+4編碼中的后4位數字與前5位數字之間要用一個連字符隔開).
* **文本**
999 1st Avenue,Bigtown,NY,11222
123 High Street,Any City,MI 48034-1234
* **正則表達式**
`\d{5}(-\d{4})?`
* **結果**
999 1st Avenue,Bigtown,NY,`11222`
123 High Street,Any City,MI `48034-1234`
### 中國郵政編碼
編碼規則
1. 共6位數字
2. 前兩位表示省、市、自治區。其中第二位不為8(港澳前兩位為99,其余省市為0-7)
3. 第三位代表郵區,第四位代表縣、市,最后兩位代表投遞郵局。
* **正則表達式**
`\d(9|[0-7])\d{4}`
### 加拿大郵政編碼
編碼規則:
1. 由6個交替出現的字母和數字字符構成,字母不區分大小寫。
2. 前3個字符用來給出FSA代碼(forward sortation area,地區代碼,2個字母中間夾一個數字),第一個字符用來表明省、市或地區(這個字符有18種合法的選擇:ABCEGHJKLMNPRSTVXY)
3. 后3個字符用來給出LDU代碼(local delivery unit,街道代碼,2個數字中間夾一個字母)
4. FSA代碼和LDU代碼之間通常要用一個空格隔開。
* **文本**
123 4th Street,Toronto,Ontario,M1A 1A1
567 8th Avenue,Montreal,Quebec,H9Z 9Z9
* **正則表達式**
`[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d`
* **結果**
123 4th Street,Toronto,Ontario,`M1A 1A1`
567 8th Avenue,Montreal,Quebec,`H9Z 9Z9`
### 美國社會安全號碼(SSN:Social Security Number)
編碼規則
1. 由3組以連字符隔開的數字構成:
2. 第1組包含著3位數字,
3. 第2組包含著2位數字,
4. 第3組包含著4位數字。
* **文本**
John Smith:123-45-6789
* **正則表達式**
`\d{3}-\d{2}-\d{4}`
* **結果**
John Smith:`123-45-6789`
### 中華人民共和國公民身份證號碼
編碼規則
1. 15位或者18位
2. 前6位是戶口所在地編碼,其中第一位是1~8;
3. 此后是出生年月日。出生年份的前兩位只能是18、19、20,而且是可選的(兼顧15位),月份
中第一位只能是0或者1,日期的第一位只能是0~3;
4. 最后一位校驗碼是數字或者X,可選(兼顧15位)。
* **正則表達式**
`[1-8]\d{5}((18)|(19)|(20))?\d{2}[0-1]\d[0-3]\d{4}[\dx]?`
### IPV4地址
編碼規則
1. 由4個字節構成(這4個字節的取值范圍都是0~255)。
2. 通常被寫成4組以`.`字符隔開的整數(每個整數由1~3位數字構成)。
3. 每組數字可以是
* 1位或2位數字
* 以`1`開頭的3位數字
* 以`2`開頭,第2位數字在0~4之間的3位數字
* 以`25`開頭,第3位數字在0~5之間的3位數字
* **文本**
localhost is 127.0.0.1.
* **正則表達式**
`(((\d{1,2})1(1\d{2})1(2[0-4]\d)1(25[0-5])).){3}((\d{1,2})1(1\d{2})|(2[0-4]\d)1(25[0-5]))`
* **結果**
localhost is `127.0.0.1`.
### URL地址
在最簡單的情況下,你的URL匹配模式至少應該匹配到以下內容:
1. 協議名(http或https)、
2. 一個主機名、一個可選的端口號
3. 一個文件路徑。
* **文本**
http://www.forta.com/blog
https://www.forta.com:80/blog/index.cfm
http://www.forta.com
http://ben:password@www.forta.com/
http://localhost/index.php?ab=1&c=2
http://localhost:8500/
* **正則表達式**
`https?://[-\w.]+(:\d+)?(/([\w/_.]*)?)?`
* **結果**
`http://www.forta.com/blog`
`https://www.forta.com:80/blog/index.cfm`
`http://www.forta.com`
`http://ben`:password@www.forta.com/
`http://localhost/index.php?`ab=1&c=2
`http://localhost:8500/`
### 完整的URL地址
下面是一個更完備(也更慢)的URL地址匹配模式,它還可以匹配:
1. URL查詢字符串(嵌在URL地址里的變量信息。這些信息與URL地址中的網址部分要用一個`?`隔開)
2. 以及可選的用戶登錄信息(用戶名和口令,兩者用`:`隔開最后跟`@`,文本中第4行)。
* **文本**
http://www.forta.com/blog
https://www.forta.com:80/blog/index.cfm
http://www.forta.com
http://ben:password@www.forta.com/
http://localhost/index.php?ab=1&c=2
http://localhost:8500/
* **正則表達式**
`https?://(\w*:\w*@)?[-\w.]+(:\d+)?(/([\w/_.]*(\?\S+)?)?)?`
* **結果**
`http://www.forta.com/blog`
`https://www.forta.com:80/blog/index.cfm`
`http://www.forta.com`
`http://ben:password@www.forta.com/`
`http://localhost/index.php?ab=1&c=2`
`http://localhost:8500/`
### 電子郵件地址
* **文本**
My name is Ben Forta,and my
email address is ben@forta.com.
* **正則表達式**
`(\w+\.)*\w+@(\w+\.)+[A-Za-z]+`
* **結果**
My name is Ben Forta,and my
email address is `ben@forta.com`.
* **分析**
`(\w+\.)*\w+`負責匹配電子郵件地址里的用戶名部分(@之前的所有文本):`(\w+\.)*`匹配一些由`.`結束的文本的零次或多次重復出現,`\w+`匹配必不可少的文本(這個組合將匹配ben和ben.forta等)。
`@`匹配@字符本身。
`(\w+\.)`匹配至少一個以`.`結束的字符串
`[A-Za-z]+`匹配頂級域名(com,edu,us或uk,等等)。
合法的電子郵件地址必須在排版格式方面同時滿足許多項規定。這個模式不能用來匹配每一種可能的電子郵件地址。 比如說,這個模式會認為ben..forta@forta.com是一個合法匹配(但這顯然不是一個合法的電子郵件地址);它不能用來匹配以IP地址做為主機名的電子郵件地址(但這種電子郵件地址是合法的)。 不過,因為絕大多數電子郵件地址都能與這個模式相匹配,所以你不妨先用它試試,如果效果不佳再考慮對之進行改進。
### HTML注釋
HTML頁面里的注釋必須被放在`<!--`和`-->`標簽之間(這兩個標簽必須至少包含兩個連字符,多于兩個沒有關系)。 在瀏覽(或調試)Web頁面的時候,我們往往需要把所有的注釋都找出來。
* **文本**
~~~
<!--Start of page-->
<HTML>
<!--Start of head-->
<HEAD>
<TITLE>MV Title</TITLE>
<!--Page title-->
</HEAD>
<!--Body-->
<BODY>
~~~
* **正則表達式**
`<!-{2,}.*?-{2,}>`
* **結果**
~~~
`<!--Start of page-->`
<HTML>
`<!--Start of head-->`
<HEAD>
<TITLE>My Title</TITLE> `<!--Page title-->`
</HEAD>
`<!--Body-->`
<BODY>
~~~
* **分析**
`<!-{2,}`匹配HTML注釋的開始標簽,也就是`<!`后面緊跟著兩個或更多個連字符的情況。
`.*?`匹配HTML注釋的文字部分(注意,這里用的是一個懶惰型元字符)。
`-{2,}>`匹配HTML注釋的結束標簽.
### JavaScript注釋
JavaScript(其他腳本語言如ActionScript和IECMA Script的其他變體等)代碼里的注釋都以//開頭。 正如剛才那個HTML注釋的例子所示,把某給定頁面里的所有注釋全部查找出來是很有用的。
* **文本**
~~~
<SCRIPT LANGUAGE="JavaScript">
// Turn off fields used only by replace
function hideReplaceFields(){
document.getElementById('RegExReplace').disabled=true;
document.getElementBvId('replaceheader').disabled=true;
}
// Turn on fields used only by replace
function showReplaceFields(){
document.getElementById('RegExReplace').disabled=false;
document.getElementById('replaceheader').disabled=false;
}
~~~
* **正則表達式**
`//.*`
* **結果**
~~~
<SCRIPT LANGUAGE="JavaScript">
`// Turn off fields used only by replace`
function hideReplaceFields(){
document.getElementById('RegExReplace').disabled=true;
document.getElementById('replaceheader').disabled=true;
}
`// Turn on fields used only by replace`
function showReplaceFields(){
document.getElementById('RegExReplace').disabled=false;
document.getElementById('replaceheader').disabled=false;
}
~~~
* **分析**
這是一個很簡單的模式:`//.*`匹配`//`和緊隨其后的注釋內容。
### 信用卡號碼
**MasterCard卡**
1. 總長為16位數字
2. 第1位是5
3. 第2位是1~5
正則表達式:`5[1-5]\d{14}`
**Visa卡**
1. 總長為13位或16位數字
2. 第1位是4
正則表達式:`4\d{12}(\d{3})?`
**美國運通卡(Amex)**
1. 總長為15位數字
2. 第1位是3
3. 第2位是4或7
正則表達式:`3[47]\d{13}`
**Discover卡**
1. 總長為16位數字
2. 前4位是6011
正則表達式:`6011\d{12}`
**Diners Club卡**
1. 總長為14位數字
2. 以300~305、36或38開頭
正則表達式:`(30[0-5]|36\d|38\d)\d{11}`
* **文本**
MasterCard:5212345678901234
Visa1:4123456789012
Visa2:4123456789012345
Amex: 371234567890123
Discover:6011123456789012
Diners Club:38812345678901
* **正則表達式**
`(5[1-5]1d14})|(4\d{12}(\d13})?)|(3[47]\d{13})|(6011\d{12})|((30[0-5]|36\d|38\d)\d{11})`
* **結果**
MasterCard:`5212345678901234`
Visa1:`4123456789012`
Visa2:`4123456789012345`
Amex:`371234567890123`
Discover:`6011123456789012`
Diners Club:`38812345678901`
* **分析**
這個模式用`|`操作符(正則表達式語言中的邏輯或操作符)把前面得到的5個模式結合到了一起。有了它,我們就可以一次完成對5種常見信用卡的號碼格式進行檢查了。
>[info] 這里使用的模式只能檢查信用卡的號碼是不是以正確的數字序列開頭和是不是有著正確的總長度。 不過,并非所有以4開頭的13位數字都是合法的Visa卡號,信用卡號碼還必須滿
足一個名為`Mod 10`的數學算法(這個算法適用于所有的信用卡類型)。 在對信用卡進行編程處理的時候,`Mod 10`算法是一個必不可少的重要環節,但這項檢查不屬于正則表達式的工作,因為正則表達式不涉及數學運算。
## 資源
1. Ben Forta 撰寫的 Sams Teach Yourself RegularExpressions in 10 Minutes 。《正則表達式必知必會》https://www.regular-expressions.info。ISBN:978-7-115-37799-9, 索書號TP30/437
2. [[Regular Exprssion Tester]](http://www.forta.com/books/0672325667)
3. [在線工具](http://c.runoob.com/front-end/854)
- WebAPP
- Linux Command
- 入門
- 處理文件
- 查找文件單詞
- 環境
- 聯網
- Linux
- Linux目錄配置標準:FHS
- Linux文件與目錄管理
- Linux賬號管理與ACL權限設置
- Linux系統資源查看
- 軟件包管理
- Bash
- Daemon/Systemd
- ftp
- Apache
- MySQL
- Command
- Replication
- mysqld
- remote access
- remark
- 限制
- PHP
- String
- Array
- Function
- Class
- File
- JAVA
- Protocals
- http
- mqtt
- IDE
- phpDesigner
- eclipse
- vscode
- Notepad++
- WebAPI
- Javasript
- DOM
- BOM
- Event
- Class
- Module
- Ajax
- Fetch
- Promise
- async/await
- Statements and declarations
- Function
- Framwork
- jQurey
- Types
- Promise
- BootStrap
- v4
- ThinkPHP5
- install
- 定時任務
- CodeIgniter
- React.js
- node.js
- npm
- npm-commands
- npm-folder
- package.json
- Docker and private modules
- module
- webpack.js
- install
- configuration
- package.json
- entry
- modules
- plugins
- Code Splitting
- loaders
- libs
- API
- webpack-cli
- Vue.js
- install
- Compile
- VueAPI
- vuex
- vue-router
- vue-devtools
- vue-cli
- vue-loader
- VDOM
- vue-instance
- components
- template
- Single-File Components
- props
- data
- methods
- computed
- watch
- Event-handling
- Render Func
- remark
- 案例學習
- bootstrap-vue
- modal
- fontAwesome
- Hosting Font Awesome Yourself
- using with jquery
- using with Vue.js
- HTML
- CSS
- plugins
- Chart.js
- D3.js
- phpSpreadSheet
- Guzzle
- Cmder
- Git
- git命令
- git流程
- Postman
- Markdown
- Regular Expressions
- PowerDesigner
- 附錄1-學習資源