| 正規表示法簡介 |
|---|
|
我們經常要用同一指令同時處理很多檔案,
或要進行搜尋/取代某一類字串時
正規表示法(Regular Expression)是威力非常強大的一種表達方式,
讓使用者很方便很精準的表達某一類字串。
|
|
例如:當我們想要利用 ex 編輯指令將一個HTML檔案裡面的所有
表格加上底色,語法是把表格標籤 <table> 加上底色屬性,成為
<table bgcolor=white>。
我們希望不需要逐一找出所有的表格標籤編輯,
而是希望能下一道編輯指令即可達到目的。
假設而HTML檔案內有兩種表格標籤,<table>、<Table>,
如果不使用Regular Expression, ex 編輯器需要兩個指令達到目的:
是故,這個編輯指令作用為:從第一行到最後一行,將字串 "<table" 及 "<Table" 取代為 再者,上面的編輯指令能保留表格標籤中原有的屬性定義。 如果檔案內的table 標籤有多種不同的大小寫寫法, Regular Expression 照樣可以應付裕如。 |
|
Regular Expression,中文譯名是百花齊放:
正規表示式、規律表達式、正規表達式、正規表示法、規則運算式、常規表示法,等等。
Unix 系統裡的很多工具都提供了 Regular Expression
的功能,大約三四十個特殊符號,只要學會其中常用的幾個符號,
就能在搜尋字串/代換字串的任務中發揮強大的威力。
|
| Regular Expression 歷史 |
|---|
|
Regular Expression 其實是自動機理論中的一種基本概念,
一個語言如果是被歸類為Regular Expression,
那麼用這個語言所表達的字串都可以用有限狀態機(Finite
State Automata)或更高等級的自動機來解析。
Ken Tompson為了方便字串比對定義了一套符號系統用在編輯器QED的字串比對
及取代這兩項功能上, 而這套符號系統是符合Regular
Expression的一種語言,並未有正式的命名,我們姑且名之為
KRE (Ken's Regular Expression)。
Unix上的編輯器ed、ex、sed以及 grep 都採用了KRE。由於引入了KRE,Unix
的威力大增,對於Unix 的推廣起到了推波助瀾的作用。
此後,KRE被廣泛地應用於各種Unix或類Unix系統的工具中。
後來POSIX將KRE補上幾個符號定義了BRE(Basic Regular Expression),
後來更擴充成 ERE(Extended Regular Expression)。
後來出現的perl 更將 BRE/ERE 大幅擴充(稱為Perl Compatible Regular
Expressions, PCRE),威力倍增。
時至今日,任何含有字串處理功能的程式語言如果沒有納入Regular
Expression,絕無生存的空間。
所幸KRE所用的符號通用於所有具字串處理的程式語言中,任何人只要熟悉了
KRE,在任一個程式語言中不須重新學習新的符號系統,只須學習擴充部分。
時至今日,各種程式語言所提供的 Regular Expression 都統稱為
RegExp,而對於 RegExp 的熟悉程度,
已經成為評價軟體工程師的一個重要指標。
|
|
下面這個網站 https://regex101.com/ 提供了一個練習 RegExp 的平台,
可以測試各種 RegExp 表達式,並對使用者輸入的字串做測試。
網站也會解釋你打了甚麼規則,所匹配的字串等,是一個不錯的練習與
測試平台。
|
| 檔案的萬用字元 |
|---|
|
其實我們常用的檔案名稱的萬用字元(Wildcard)也是一種
Regular Expression,但通常軟體工程師都會將RegExp 及 Wildcard
分開,RegExp 不包含 Wildcard。
|
| * | 代表任意長度的字元
| ?
| 代表任意一個字元
| [ ]
| 括弧內的任一個字元
| |
|---|
|
例:
|
| a* | 代表所有a開頭的檔案名稱
| a?
| 代表所有a開頭而長度為二的檔案名稱
| a[1-9]
| 代表所有a開頭而第二字為 1-9 中任意數字的檔案名稱
| |
|---|
|
這些該是耳熟能詳的吧?並不盡然,請看看下面兩個指令:
|
ls a[1-9] echo a[1-9] |
|---|
|
這兩個指令是否產生相同的結果?
|
|
大部份的人知道第一行指令的結果,
但卻認為第二行指令會產生下面的結果。
|
a1 a2 a3 a4 a5 a6 a7 a8 a9 |
|---|
|
其實這兩個指令所產生的結果完全一樣,
|
|
在執行第二行指令時,shell 會先找到a[1-9]這個字串,
認定它是檔案名稱,先行找到該目錄中所有符合a[1-9]
這個Wildcard的檔案名稱,再叫出echo,
並將所找出來的檔案名稱傳給它,而echo則將拿到的檔案名稱
以字串方式一一印出於STDOUT。
|
|
因此請緊緊記住,當shell把一個字串當成檔案名稱時,
shell都會去所在目錄找出所有符合條件的檔案名稱,再展開成字串。
|
|
如果要印出 a1 a2 a3 a4 a5 a6 a7 a8 a9
這樣的字串,應該使用 Range Generator 如下:
|
| 字串的Regular Expression |
|---|
|
搜尋字串時所用的RegExp方面用處更大了,筆者幾乎天天離不了它。
軟體界談到RegExp時,通常專指字串比對時使用的,
少有人在檔案萬用字元使用 RegExp,縱使兩者都是一種Regular
Expression。我們介紹 POSIX 定義的 Basic Regular Expression
(BRE) 以及 Extended Regular Expression (ERE)。 值得注意的是:
ERE 除了增加一些符號之外,還將一些與BRE共有的符號簡化了,
雖然比較簡潔,但是卻失去了相容性。換言之,
ERE 引擎不一定能成功解析用 BRE 寫的RegExp。
|
| POXIS Regular Expression |
|---|
|
POSIX BRE (Basic Regular Expression) 特殊字元 (metacharacter)
|
| . | 代表任意字元
| *
| 代表前面的字元出現任意多次(包括零次)
| ^
| 代表一行字串的開頭
| $
| 代表一行字串的結尾
| [...]
| 代表中括弧內的任一個字元都是待搜字元
| [abcd] # 代表a或b或c或d 都是待搜字元 [a-d] # 代表a或b或c或d 都是待搜字元 [0-9] # 代表 [0123456789] 都是待搜字元 [0-9a-fA-F] # 代表 [0123456789abcdefABCDEF] 都是待搜字元 [-abcd] # '-'、'a'、'b'、'c'、'd'都是待搜字元 []abcd] # ']'、'a'、'b'、'c'、'd'都是待搜字元 []abcd-] # ']'、'-' 'a'、'b'、'c'、'd'都是待搜字元 [^a]
| 代表不是a的任意字元
| | 代表不是a或b或c或d的任意字元
| | 前面的字元重複至少n次,至多m次
| \{n\} 前面的字元重複正好n次 \{n,\} 前面的字元重複至少n次 \
| Escape (將後面的特殊字元取消特殊意義),例外:
'\{', '\}', '\(', '\)', '\<', '\>', '\b', '\B', '\w', '\W', '\`', '\'', '\+', 以及 '\?'.
| \( \)
| 將夾在 \( 及 \) 中的字串標記並儲存以備後面重複使用 (Back Reference)
| \n
| 引用前面第 n 個標記的匹配內容
| [:class:]
| 代表中括弧內的類別中任一個字元都是待搜字元 | 類別包括 [:alpha:], [:upper:], [:lower:], [:alnum:], [:blank:], [:space:], [:digit:], [:xdigit:], [:cntrl:], [:print:], [:graph:], [:punct:],
|
|---|
|
POSIX ERE (Extended Regular Expression)
|
|
與 BRE 相異之特殊字元 (metacharacter)
|
|
增加之特殊字元
|
|
減少之特殊字元
|
|
Unix 各個工具所使用的 RegExp
|
| 語法 | grep | sed | sed -E | ed | ex/vi | more | egrep | awk | lex
| BRE
| Y
| Y
|
| Y
| Y
| Y
|
|
| | ERE
|
|
| Y
|
|
|
| Y
| Y
| Y
| |
|---|
| Email Format Check |
|---|
| (1) | 中間一定要出現一個 @
| (2)
| 必須以一個以上的文字或數字開頭
| (3)
| @ 之前可以出現 1 個以上的文字、數字與「-」的組合,例如 -abc-
| (4)
| @ 之前可以出現 1 個以上的文字、數字與「.」的組合,例如 .abc.
| (5)
| @ 之前以上兩項以 or 的關係出現,並且出現 0 次以上
| (6)
| @ 之後出現一個以上的大小寫英文及數字的組合
| (7)
| @ 之後只能出現「.」或是「-」,但這兩個字元不能連續時出現
| (8)
| @ 之後出現 0 個以上的「.」或是「-」配上大小寫英文及數字的組合
| (9)
| @ 之後出現 1 個以上的「.」配上大小寫英文及數字的組合,結尾需為大小寫英文
| |
|---|
| Email Format Check |
|---|
| (1) | 中間一定要出現一個 @
| (2)
| 必須以一個以上的文字或數字開頭
| (3)
| @ 之前可以出現 1 個以上的文字、數字與「-」的組合,例如 -abc-
| (4)
| @ 之前可以出現 1 個以上的文字、數字與「.」的組合,例如 .abc.
| (5)
| @ 之前以上兩項以 or 的關係出現,並且出現 0 次以上
| (6)
| @ 之後出現一個以上的大小寫英文及數字的組合
| (7)
| @ 之後只能出現「.」或是「-」,但這兩個字元不能連續時出現
| (8)
| @ 之後出現 0 個以上的「.」或是「-」配上大小寫英文及數字的組合
| (9)
| @ 之後出現 1 個以上的「.」配上大小寫英文及數字的組合,結尾需為大小寫英文
| |
|---|
| 經驗 |
|---|
|
注意前面所提的檔名稱及這裡所提的字串的regular expression
雖然有相同的符號,但在不同的地方代表的意義是不同的,
|
|
很多人經常將兩者混在一起。
|
|
此外,另一個容易混淆的地方是:
|
|
不同的些軟體,所使用的regular expression也許有些差異,
例如 BRE 或 ERE, 甚至是POSIX 標準出來之前所使用的
Regular Expression.
|
|
以上所提的regular expression然只有幾個,但使用起來卻是
一大幫手,
所提的例子中,到處可以見到它們的蹤影,我們不在這裡多作說明,
而在各個例子中才說明。
|
|
原因是很多人看過之後,沒有實際運用,不容易體會到它們的好處。
|
|
RegExp 符號拆解說明
|
|
很多人經常將兩者混在一起。
|
|
此外,另一個容易混淆的地方是:
|
|
不同的些軟體,所使用的regular expression也許有些差異,
例如 BRE 或 ERE, 甚至是POSIX 標準出來之前所使用的
Regular Expression.
|
|
以上所提的regular expression然只有幾個,但使用起來卻是
一大幫手,
所提的例子中,到處可以見到它們的蹤影,我們不在這裡多作說明,
而在各個例子中才說明。
|
|
原因是很多人看過之後,沒有實際運用,不容易體會到它們的好處。
|
|
RegExp 符號拆解說明
|
|
RegExp 符號拆解說明
|
|
RegExp 符號拆解說明
|
| Ed Regular Expression |
|---|
|
Ed 編輯器所支援的 RegExp
|
| . | 代表任意字元
| *
| 代表前面的字元出現任意多次(包括零次)
| ^
| 代表一行字串的開頭
| $
| 代表一行字串的結尾
| [...]
| 代表中括弧內的任一個字元都是待搜字元
| [abcd] # 代表a或b或c或d 都是待搜字元 [a-d] # 代表a或b或c或d 都是待搜字元 [0-9] # 代表 [0123456789] 都是待搜字元 [0-9a-fA-F] # 代表 [0123456789abcdefABCDEF] 都是待搜字元 [-abcd] # '-'、'a'、'b'、'c'、'd'都是待搜字元 []abcd] # ']'、'a'、'b'、'c'、'd'都是待搜字元 []abcd-] # ']'、'-' 'a'、'b'、'c'、'd'都是待搜字元 [^a]
| 代表不是a的任意字元
| | 代表不是a或b或c或d的任意字元
| | 前面的字元重複至少n次,至多m次
| \{n\} 前面的字元重複正好n次 \{n,\} 前面的字元重複至少n次 \
| Escape (將後面的特殊字元取消特殊意義),例外:
'\{', '\}', '\(', '\)', '\<', '\>', '\b', '\B', '\w', '\W', '\`', '\'', '\+', 以及 '\?'.
| \( \)
| 將夾在 \( 及 \) 中的字串儲存以備後面重複使用 (Back Reference)
| \+
| 代表前面的字元出現一次或一次以上
| \?
| 代表前面的字元出現零次或一次
| \w
| 一個英文字裡的字元 (matches a character within a word)
| \W
| 非一個英文字裡的字元 (matches a character which is not within a word)
| \<
| 一個英文字的開頭 (matches the beginning of a word)
| \>
| 一個英文字的尾端 (matches the end of a word)
| \b
| 一個英文字的邊界 (matches a word boundary)
| \B
| 非一個英文字的邊界 (matches characters which are not a word boundary)
| \`
| 整個輸入的前邊界 (matches the beginning of the whole input)
| \'
| 整個輸入的後邊界 (matches the end of the whole input)
| [:class:]
| 代表中括弧內的類別中任一個字元都是待搜字元 | 類別包括 [:alpha:], [:upper:], [:lower:], [:alnum:], [:blank:], [:space:], [:digit:], [:xdigit:], [:cntrl:], [:print:], [:graph:], [:punct:],
|
|---|
|
POSIX Basic and Extended Regular Expression (BRE and ERE)
|
| Character | | Meaning in a pattern
| 字元 | | 意義
| +
| ERE
| 代表前面的字元出現一次或一次以上 (#KRE 不支援 ) | ?
| ERE
| 代表前面的字元出現零次或一次 | \
| Both
| Usually, turn off the special meaning of the following character.
Occasionally, enable a special meaning for the
following character, such as
for \(...\) and \{...\}.
| .
| Both
| Match any single character except NUL.
Individual programs may also
disallow matching newline.
| *
| Both
| Match any number (or none) of the single
character that immediately
precedes it. For EREs, the preceding character can
instead be a regular expression.
| For example, since . (dot) means any character, .* means "match any number of any character." For BREs, * is not special if it's the first character of a regular expression. *
| Both
| Match any number (or none) of the single
character that immediately
precedes it. For EREs, the preceding character can
instead be a regular expression.
| For example, since . (dot) means any character, .* means "match any number of any character." For BREs, * is not special if it's the first character of a regular expression. ^
| Both
| Match the following regular expression at the
beginning of the line
or string.
| BRE: special only at the beginning of a regular expression. ERE: special everywhere. $
| Both
| Match the preceding regular expression at the
end of the line or string.
| BRE: special only at the end of a regular expression. ERE: special everywhere. [...]
| Both
| Termed a bracket expression, this matches
any one of the enclosed characters.
| A hyphen (-) indicates a range of consecutive characters. (Caution: ranges are locale-sensitive, and thus not portable.) A circumflex (^) as the first character in the brackets reverses the sense: it matches any one character not in the list. A hyphen or close bracket (]) as the first character is treated as a member of the list. All other metacharacters are treated as members of the list (i.e., literally). Bracket expressions may contain collating symbols, equivalence classes, and character classes. \{n,m\}
| BRE
| Termed an interval expression, this
matches a range of
occurrences of the single character that immediately
precedes it.
| \{n\} matches exactly n occurrences, \{n,\} matches at least n occurrences, and \{n,m\} matches any number of occurrences between n and m. n and m must be between 0 and RE_DUP_MAX (minimum value: 255), inclusive. "exactly five occurrences of a" and "between 10 and 42 instances of q" are written a\{5\} and q\{10,42\}, respectively. {n,m}
| ERE
| Just like the BRE \{n,m\} earlier, but
without the backslashes in front of the braces.
| {n}, {n,}, {n,m}, a{5, q{10,42} \( \)
| BRE
| Save the pattern enclosed between \( and \)
in a special holding
space. Up to nine subpatterns can be saved on a single
pattern. The text
matched by the subpatterns can be reused later in the
same pattern, by the
escape sequences \1 to \9. For example, \(ab\).*\1
matches two occurrences of
ab, with any number of characters in between.
| ( )
| ERE
| Apply a match to the enclosed group of regular
expressions.
| \n
| BRE
| Replay the nth subpattern enclosed in \( and \)
into the pattern at
this point. n is a number from 1 to 9, with 1 starting
on the left.
| +
| ERE
| Match one or more instances of the preceding
regular expression.
| ?
| ERE
| Match zero or one instances of the preceding
regular expression.
| |
| ERE
| Match the regular expression specified before or
after.
| |
|---|
| Perl Compatible Regular Expression |
|---|
|
Perl Compatible Regular Expression
|
|
Perl 在 POSIX ERE 的基礎上擴充了一些功能,非常方便,
也被許多其他程式語言使用,例如 Python、PHP 和 JavaScript。
|
| \r | Carridge Return
| \t
| Horizontal Tab
| \f
| Form Feed
| \n
| New Line
| \N
| not \n
| \s
| 空白、\t, \r, \f, \n
| \S
| not \s
| \w
| [a-zA-Z0-9_]
| \W
| not \w
| \d
| [0-9]
| \D
| [^0-9], not \d
| \b
| 英文字的邊界 (word boundry)
| |
|---|
| RegExp 範例:使用前後端定錨 |
|---|
|
欲匹配的文字: abcABCdefDEF
|
| RegExp 樣式 | 匹配結果 | 理由
| ABC
| Yes
| 字串含有 'ABC'
| ^ABC
| No
| 字串雖含有 'ABC',但不在開頭
| def
| Yes
| 字串含有 'def'
| def$
| No
| 字串雖含有 'def',但不在末端
| [[:upper:]]\{3\}
| Yes
| 字串含有連續三個大寫英文字母
| [[:upper:]]\{3\}$
| Yes
| 字串在末端含有連續三個大寫英文字母
| ^[[:alpha:]]\{3\}
| Yes
| 字串在前端含有連續三個英文字母
| |
|---|
| Examples: Anchoring text matches |
|---|
|
Text to be matched: abcABCdefDEF
|
| Pattern | Matches? | Text matched/Reason match fails
| ABC
| Yes
| abcABCdefDEF
| ^ABC
| No
| Match is restricted to beginning of string
| def
| Yes
| abcABCdefDEF
| def$
| No
| Match is restricted to end of string
| [[:upper:]]\{3\}
| Yes
| Characters 4, 5, and 6, in the
middle: abcABCdefDEF
| [[:upper:]]\{3\}$
| Yes
| Characters 10, 11, and 12, at
the end: abcDEFdefDEF
| ^[[:alpha:]]\{3\}
| Yes
| Characters 1, 2, and 3, at the
beginning: abcABCdefDEF
| |
|---|
| 運用RegExp於 Sed 中的實例 |
|---|
|
|
|
|
|
|
|
|
|
|
|
| |
| 複雜的 RegExp |
|---|
|
在 shell script 中利用 RegExp 處理字串,通常只需要用到簡單的符號及其組合,而KRE 或
BRE
在大部分的情況是足夠了。而且處理字串時(例如取代或刪除)RegExp
必須非常謹慎,以免取代或刪除了不該更動的地方。
例如一個 sed 的取代指令 's/[Tt]he/THE/'
就可能誤將很多其他的英文字 改掉了,例如there 被改成
THEre,而通常使用RegExp時是批量處理,下指令的人沒有親眼看到每一個被
更改的地方,很可能對錯誤毫無知覺,造成無法彌補的損害而不自知。
我們強烈建議不要使用太複雜的 RegExp 於取代或刪除這種危險的動作。
|
|
Regular Expression 在大數據的應用
|
|
現在的資訊世界越來越仰賴大數據的運用,而在海量的資訊中撈取使用者有興趣的資料,
那就需要精準的搜尋了,如果搜尋條件太緊的話,會漏掉需要的資訊,
反之,如果搜尋條件太鬆的話,會撈出太多無關的資訊,淹沒了所需要的資訊。因此,
精準的搜尋在大數據相關應用中,非常重要。以電話號碼為例,如果要從一堆檔案中,
撈出所有的電話號碼,那是非常頭疼的一項任務,因為電話號碼有太多的表達形式,
舉例而言,至少有以下幾種常見的格式:
|
| 貪婪模式與非貪婪模式 |
|---|
|
RegExp 的「貪婪模式」(Greedy mode)是指量詞(如 *、+、{n,m})
等符號在解析時預設解析引擎會盡可能抓取最長的字串。
若要改成「非貪婪模式」(Non-greedy/Lazy mode),
只要在量詞後面加上問號"?"即可。假設有如下一段 HTML 字串:
|
| 貪婪模式 | <b>..*</b> | 會一口氣匹配從第一個 <b> 到最後一個
</b> 之間的整段字串,
<b>abc</b><b>def</b> 非貪婪模式
| <b>..*?</b>
| 只會匹配到
| <b>abc</b> |
|---|
| 反向參照 (Back References) |
|---|
|
RegExp 中的 Back References 中文稱為「反向參照」或「向後參考」。
它的核心概念是用小括號 \( \)
標記匹配到的字串作為參考字串,
並在同一個表達式後面用 \1、\2
等編號來引用前面已經匹配到的內容。
|
|
X.1 核心概念與語法
|
| 標記匹配字串 | | 將括號內的RegExp所匹配到結果儲存起來,以備重複使用。
| 引用全部匹配字串
| &
| 將匹配到的字串全部引用
| 引用標記部分匹配字串
| \n
| n 是 1 至 9 的數字。
| |
|---|
|
X.2 主要的應用
|
|
X.2.1 在字串取代時,代入匹配到的字串
|
|
X.2.2 比對重複字
|
|
例如,下面的 RegExp
|
|
X.2.3 匹配成對的標籤
|
|
例如: 要從 一個 HTML 文字檔中找出所有含有
"<H3> .. <H6>" 成對的標籤之行:
|
|
RegExp 符號拆解說明
|
|
匹配標籤可能會用到非貪婪模式,要在"..*"之後加問號"?"
|
|
RegExp 符號拆解說明
|
|
範例
|
| Back References | match whatever an earlier part of the regular expression matched |
|---|
|
Back Reference exists in BRE only, not in ERE.
|
| Step 1 | to enclose a subexpression in \( and \).
There may be up to nine enclosed subexpressions within a single pattern, and they may be nested. Step 2
| to use \digit, where digit is a
number between 1 and 9, in a
later part of the same pattern.
| Its meaning there is "match whatever was matched by the nth earlier parenthesized subexpression." |
|---|
|
Examples
|
| 輸入資料檢核 |
|---|
|
現代的資訊系統常常要接受使用者輸入資料,例如:
身分證號,生日,密碼,email地址等。
不幸的是使用者輸入資料常有錯誤,輕則浪費系統算力,重則讓錯誤資料植入資料庫,造成不可預料的後果。
試想如果某個重要資料庫內有兩個人的身分證號碼是相同的,其引發的後果難以想像。一個健全的資訊系統都會
設法根據資料的特定規則於輸入時檢查是否符合規則,如此可以過濾大部分錯誤的資料。例如台灣的身分證號碼就有固定格式
及檢查碼。一個系統如果前後端是分別開發的,例如網頁式資訊系統,通常前端負責格式檢查,後端則負責邏輯檢查,
這是現代網頁開發中非常核心的優化手段。
而RegExp 則可以表達大部分的格式,因此可以用來檢查很多資料格式。
這種做法主要有以下幾個巨大優勢:
|
|
1. 節省伺服器算力與頻寬
|
|
如果沒有前端驗證,每一次使用者打錯字(例如 Email 少了
@、身分證字號少一碼),資料都要打包成 API
請求送到後端,後端資料庫或程式碼檢查完後再回傳錯誤訊息。這不僅浪費網路頻寬,還會平白消耗伺服器的算力。如能在前端擋下,由使用者的電腦承擔了這部分的計算,節省了伺服器的算力與頻寬。讀者會問,前端是否能完成所有檢查讓伺服器完全放心不必浪費算力於資料檢查?
現實上很難做到,一則
有些邏輯檢查是藉由資料庫內建的"完整性限制" ,Integrity
Constraint,來實現的,二則有些檢查牽涉到資安,或內部商業規則,基於資安的考慮不宜放在前端。
|
|
2. 更好的使用者體驗 (User Experience, UX)
|
|
後端驗證需要排隊等待「資料庫處理」及「來回通訊」的時間。
而前端通常是個人電腦,可以在幾毫秒內就能完成,
使用者可以立刻得到錯誤訊息。
|
|
常見的前端 RegExp 檢查範例
|
|
以下是幾個在網頁式資訊系統常見的輸入資料,
|
|
初步格式檢查:第一碼大寫英文,第二碼數字為 1 或 2 或 8 或 9, 後面接 8 碼數字。
|
|
Javascript 程式碼片段
|
|
RegExp 符號拆解說明
|
|
前端還可以進一步用 JavaScript 執行檢查碼驗證,把使用者亂填的假號碼也擋掉。
|
|
生日 (假設 YYYY-MM-DD 格式)
|
|
初步檢查是否為數字與連字號組成:
|
|
Javascript 程式碼片段
|
|
RegExp 符號拆解說明
|
|
可以進一步檢查數字的正確範圍:
|
|
Javascript 程式碼片段
|
|
RegExp 符號拆解說明
|
|
軟體設計師如果有充裕的時間,當然可以進一步用Javascript檢查月份是否介於01至12之間,日期是否介於01至31之間,
或更細膩的根據月份變動日期範圍。
|
|
電子郵件 (Email)
|
|
Email 的官方標準非常複雜,但前端通常會用一個實用的標準格式來阻擋明顯的錯誤輸入:
|
|
Javascript 程式碼片段
|
|
密碼強度檢查
|
|
現代的資訊系統的登入密碼常有強度要求,必須含有幾種特殊的字元,
例如英文大笑寫,數字等。資訊系統如能使用RegExp來驗證強度,將可省下
很多程式設計的成本,可惜一般的RegExp無法表達這種邏輯AND的條件。
所幸 Javascript所支援的RegExp提供了一種
正面預覽(positive lookaheads)及 負面預覽 (negative lookaheads)
的功能,讓系統在執行RegExp之前先掃描一下目標字串看是否有符合模板
的字串,掃描完後再將指標指到目標字串之前頭再執行下一個RegExp指令,
如此可以再次拿目標字串來比對,達到邏輯AND的功能。
正面預覽為篩選(selective)而負面預覽為過濾(filtering)。
|
|
假設密碼強度要求:至少含有一個英文字母和一個數字
|
|
Javascript 程式碼片段
|
|
RegExp工作原理:
|
|
假設密碼強度要求:只能使用而且必須含有英文大小寫字母、數字,且長度為 8~20 碼。
|
|
Javascript 程式碼片段
|
|
RegExp 符號拆解說明
|
|
SSN (Social Security Number) 美國社會安全號碼
|
|
SSN 是美國社會安全號碼,相當於我國的身分證號碼,其重要性不言可喻。
其規則如下:
|
| 正好9個數字 It should have 9 digits. 分成三段,用'-'隔開 | It should be divided into 3 parts by hyphen (-). 第一段為3個數字,排除000, 666, 900-999等數字 | The first part should have 3 digits and should not be 000, 666, or between 900 and 999. 第二段為01-99之2位數 | The second part should have 2 digits and it should be from 01 to 99. 第三 段為0001-9999之4位數 | The third part should have 4 digits and it should be from 0001 to 9999. |
|---|
|
SSN 規則中排除一些數字,必須使用負面預覽功能
|
|
Javascript 程式碼片段
|
|
RegExp 符號拆解說明
|
| Bracket Regular Expression |
|---|
|
Character classes
|
|
represent classes of
characters, such as digits, lower- and uppercase
letters, punctuation,
whitespace, and so on.
|
|
They are written by enclosing
the name of the class in
[: and :].
|
|
The pre-POSIX range
expressions for decimal and hexadecimal digits can
(and should) be expressed
portably, by using character classes: [[:digit:]] and
[[:xdigit:]].
|
|
POSIX character classes
|
| 類別 (Class) | 符合的字元 (Matching
characters)
| [:digit:]
| 數字,相當於 [0-9] | Numeric characters [:xdigit:]
| 16進位數字,相當於 [0-9A-Fa-f] | Hexadecimal digits [:alnum:]
| 英數字,相當於 [a-zA-Z0-9] | Alphanumeric characters [:alpha:]
| 英文字母,相當於 [a-zA-Z] | Alphabetic characters [:lower:]
| 小寫英文字母,相當於 [a-z] | Lowercase characters [:upper:]
| 大寫英文字母,相當於 [A-Z] | Uppercase characters [:cntrl:]
| 標點符號 | Control characters [:print:]
| 可印字元 | Printable characters [:punct:]
| 標點符號 | Punctuation characters [:space:]
| 空白、空格以及 \r, \f
等控制字元 | Whitespace characters [:blank:]
| 空白以及空格 | Space and tab characters [:graph:]
| 除[:space:]及[:cntrl:]以外之所有可視字元 | Nonspace characters |
|---|
| Bracket Regular Expression |
|---|
|
Collating
|
|
the act of giving an ordering to some group or set of items.
|
|
A POSIX collating element consists of the name of the
element in the current
locale, enclosed by [. and .].
|
|
For example, in Czech and Spanish, the two characters
ch are kept
together and are treated as a single unit for
comparison purposes
|
|
Thus, [ab[.ch.]de] matches any of the characters a, b, d, or
e, or the pair ch.
It does not match a standalone c or h character. |
| Bracket Regular Expression |
|---|
|
Equivalence class
|
|
used to represent different
characters that should be treated the same when matching.
|
|
Equivalence classes enclose the name of the
class between [= and =].
|
|
For example, in a French locale, there might be an
[=e=] equivalence class. If it exists, then the
regular expression
[a[=e=]iouy] would match all the lowercase English
vowels, as well as the letters e`, e', and so on.
|
| Bracket Regular Expression |
|---|
|
Collating elements, equivalence classes, and character
classes are only
recognized inside the square brackets of a bracket
expression. Writing a
standalone regular expression such as [:alpha:]
matches the characters a, l,
p, h, and :. The correct way to write it is
[[:alpha:]].
|
|
Within bracket expressions, all other metacharacters
lose their special
meanings. Thus, [*\.] matches a literal asterisk, a
literal backslash, or a
literal period. To get a ] into the set, place it
first in the list: [ ]*\.]
adds the ] to the list. To get a minus character into
the set, place it first
in the list: [-*\.]. If you need both a right bracket
and a minus, make the
right bracket the first character, and make the minus
the last one in the
list: [ ]*\.-].
|
|
Finally, POSIX explicitly states that the NUL
character (numeric value zero)
need not be matchable. This character is used in the C
language to indicate
the end of a string, and the POSIX standard wanted to
make it straightforward
to implement its features using regular C strings. In
addition, individual
utilities may disallow matching of the newline
character by the . (dot)
metacharacter or by bracket expressions.
|
| Regular Expression Examples |
|---|
| clinton | The seven letters clinton, anywhere on a line
| ^clinton
| The seven letters clinton, at the beginning
of a line
| clinton$
| The seven letters clinton, at the end of a
line
| ^clinton$
| A line containing exactly the seven letters
clinton, and nothing
else
| [Cc]linton
| Either the seven letters Clinton, or the
seven letters clinton,
anywhere on a line
cli.ton | The three letters cli, any character, and the
three letters ton, anywhere on a line
cli.*ton | The three letters cli, any sequence of zero
or more characters, and
the three letters ton, anywhere on a line (e.g.,
cliton, clinton, cliBILLton, and so on)
| |
|---|
| Examples: {} |
|---|
| Pattern | Matches
| \{n\}
| Exactly n occurrences of the preceding regular
expression
| \{n,\}
| At least n occurrences of the preceding regular
expression
| \{n,m\}
| Between n and m occurrences of the preceding
regular expression
| |
|---|
| BRE operator precedence |
|---|
|
BRE operator precedence from highest to lowest
|
| Operator | Meaning
| [. .] [= =] [: :]
| Bracket symbols for character
collation
| \metacharacter
| Escaped metacharacters
| [ ]
| Bracket expressions
| \( \) \digit
| subexpressions and backreferences
| * \{ \}
| Repetition of the preceding
single-character regular expression
| no symbol
| Concatenation
| ^ $
| Anchors
| |
|---|
| Extended Regular Expression |
|---|
|
EREs, as the name implies, have more capabilities than
do basic regular
expressions. Many of the metacharacters and
capabilities are identical.
However, some of the metacharacters that look similar
to their BRE counterparts have different meanings.
|
|
Matching single characters
|
|
EREs are essentially the same as
BREs.
|
|
Exceptions
|
|
in awk, \ is special inside bracket
expressions.
Thus, to match a left bracket, dash, right bracket, or backslash, you could use [\[\-\]\]. |
|
Backreferences don't exist
|
|
Parentheses are special in EREs, but
serve a different purpose than they do in BREs
In an ERE, \( and \) match literal left and right
parentheses.
|
|
Matching multiple regular expressions with one expression
|
|
EREs have the most notable differences from BREs in
the area of matching
multiple characters.
|
|
The * does work the same as in BREs.
|
|
An exception is that the meaning of a * as the
first character of an
ERE is "undefined," whereas in a BRE it means "match a
literal *."
|
|
Interval expressions are also available in EREs;
|
|
however, they are written
using plain braces, not braces preceded by
backslashes.
|
|
"exactly five occurrences of a" and
"between 10 and 42 instances
of q" are written a{5} and q{10,42}, respectively.
|
|
Use \{ and \} to match literal brace characters.
|
|
? and +
|
| ? | Match zero or one of the preceding regular expression
? meaning "optional." example, ab?c matches both ac and abc, but nothing else. +
| Match one or more of the preceding regular expression
| similar to the * metacharacter, except that at least one occurrence of text matching the preceding regular expression must be present. Thus, ab+c matches abc, abbc, abbbc, and so on, but does not match ac. ab+c is same as abb*c |
|---|
|
Alternation and Grouping
|
| (why)+ | matches one or more occurrences of the word why.
| [Tt]he (CPU|computer) is
| matches sentences
using either CPU or
computer in between The (or the) and is.
| (read|write)+
| matches one or more
occurrences of either
of the words read or write
| | same as above but
allow zero or more intervening whitespace between words
| matches multiple successive occurrences of either read or write, possibly separated by whitespace characters. ((read|write)[[:space:]]+)+
| same as above but
allow one or more intervening whitespace between words
| ^abcd|efgh$
| match abcd
at the beginning of the
string, or match efgh at the end of the string
| ^(abcd|efgh)$
| match a string containing
exactly abcd or exactly efgh
| |
|---|
|
Anchoring text matches
|
|
The ^ and $ have the same meaning as in BREs
|
|
In EREs, ^ and $ are always metacharacters.
Thus, regular expressions such as ab^cd and ef$gh are
valid, but cannot match anything,
|
|
ERE operator precedence
|
|
Operator precedence applies to EREs as it does to BREs.
|
|
ERE operator precedence from highest to lowest
|
| Operator | Meaning
| [. .] [= =] [: :]
| Bracket symbols for character
collation
| \metacharacter
| Escaped metacharacters
| [ ]
| Bracket expressions
| ( )
| Grouping
| * + ? { }
| Repetition of the preceding regular
expression
| no symbol
| Concatenation
| ^ $
| Anchors
| |
| Alternation
| |
|---|
| GNU Extensions |
|---|
| Operator | Meaning
| \w
| Matches any word-constituent character. Equivalent
to [[:alnum:]_].
| \W
| Matches any nonword-constituent character.
Equivalent to [^[:alnum:]_].
| \< \>
| Matches the beginning and end of a word, as
described previously.
| \b
| Matches the null string found at either the
beginning or the end of a
word. This is a generalization of the \< and \>
operators. Note: Because awk
uses \b to represent the backspace character, GNU awk
(gawk) uses \y.
| \B
| Matches the null string between two
word-constituent characters.
| \' \`
| Matches the beginning and end of an emacs
buffer, respectively. GNU
programs (besides emacs) generally treat these as
being equivalent to ^ and $.
| |
|---|
| Which Programs Use Which Regular Expressions? |
|---|
|
Unix programs and their regular expression type
|
| Type | grep | sed | ed | ex/vi | more | egrep | awk | lex
| BRE
| Y
| Y
| Y
| Y
| Y
|
|
| | ERE
|
|
|
|
|
| Y
| Y
| Y
| \< \>
| Y
| Y
| Y
| Y
| Y
|
|
| | |
|---|
| Email Format Check |
|---|
| (1) | 中間一定要出現一個 @
| (2)
| 必須以一個以上的文字或數字開頭
| (3)
| @ 之前可以出現 1 個以上的文字、數字與「-」的組合,例如 -abc-
| (4)
| @ 之前可以出現 1 個以上的文字、數字與「.」的組合,例如 .abc.
| (5)
| @ 之前以上兩項以 or 的關係出現,並且出現 0 次以上
| (6)
| @ 之後出現一個以上的大小寫英文及數字的組合
| (7)
| @ 之後只能出現「.」或是「-」,但這兩個字元不能連續時出現
| (8)
| @ 之後出現 0 個以上的「.」或是「-」配上大小寫英文及數字的組合
| (9)
| @ 之後出現 1 個以上的「.」配上大小寫英文及數字的組合,結尾需為大小寫英文
| |
|---|
| Email Format Check |
|---|
| (1) | 中間一定要出現一個 @
| (2)
| 必須以一個以上的文字或數字開頭
| (3)
| @ 之前可以出現 1 個以上的文字、數字與「-」的組合,例如 -abc-
| (4)
| @ 之前可以出現 1 個以上的文字、數字與「.」的組合,例如 .abc.
| (5)
| @ 之前以上兩項以 or 的關係出現,並且出現 0 次以上
| (6)
| @ 之後出現一個以上的大小寫英文及數字的組合
| (7)
| @ 之後只能出現「.」或是「-」,但這兩個字元不能連續時出現
| (8)
| @ 之後出現 0 個以上的「.」或是「-」配上大小寫英文及數字的組合
| (9)
| @ 之後出現 1 個以上的「.」配上大小寫英文及數字的組合,結尾需為大小寫英文
| |
|---|
| 經驗 |
|---|
|
注意前面所提的檔名稱及這裡所提的字串的regular expression
雖然有相同的符號,但在不同的地方代表的意義是不同的,
|
|
很多人經常將兩者混在一起。
|
|
此外,另一個容易混淆的地方是:
|
|
不同的些軟體,所使用的regular expression也許有些差異,
例如 BRE 或 ERE, 甚至是POSIX 標準出來之前所使用的
Regular Expression.
|
|
以上所提的regular expression然只有幾個,但使用起來卻是
一大幫手,
所提的例子中,到處可以見到它們的蹤影,我們不在這裡多作說明,
而在各個例子中才說明。
|
|
原因是很多人看過之後,沒有實際運用,不容易體會到它們的好處。
|
|
RegExp 符號拆解說明
|
|
很多人經常將兩者混在一起。
|
|
此外,另一個容易混淆的地方是:
|
|
不同的些軟體,所使用的regular expression也許有些差異,
例如 BRE 或 ERE, 甚至是POSIX 標準出來之前所使用的
Regular Expression.
|
|
以上所提的regular expression然只有幾個,但使用起來卻是
一大幫手,
所提的例子中,到處可以見到它們的蹤影,我們不在這裡多作說明,
而在各個例子中才說明。
|
|
原因是很多人看過之後,沒有實際運用,不容易體會到它們的好處。
|
|
RegExp 符號拆解說明
|
|
RegExp 符號拆解說明
|
|
RegExp 符號拆解說明
|