正規表示式簡介
簡介
- Regular Expression, 也稱為 RegExp、regex、RE、正規表示式(台灣)、正則表達式(中國)
- 用來處理符合某個句法規則的字串
- 現在的標準已經被ISO(國際標準組織)批准和被Open Group組織認定(POSIX 1003.2)
用途
指定字串樣式並加以處理
- 搜尋
- 取出資訊
- 取代
- color → colour
- 12/06/2006 → 2006-12-06
- 檢查指定格式
- Email格式檢查
哪些軟體使用正規表示式?
Unix like下的工具大都內建regex,Windows下的工具比較少,但也有逐漸增多的趨勢
各程式的regex雖大同小異,但仍有不同,不能直接轉換
- unix工具:
grep
,sed
,awk
... - 編輯器:
vi
,emacs
,notepad++
... - 程式語言:
Java
,Python
,Ruby
...
規則表
只列出常用的
位置和量詞
字元 | 說明 | 範例 |
---|---|---|
^ | 表示位置在開頭 | ^A → 開頭為A |
$ | 表示位置在結尾 | A$ → 結尾為A |
* | 比對前一個字零次或更多次 | go*gle → ggle, gogle, google... |
+ | 比對前一個字一次或更多次 | go+gle → gogle, google, gooogle... |
? | 比對前一個字零次或一次 | go?gle → ggle, gogle |
{} | 表示前面的字元或集合出現的次數 | c{1,3} → c, cc, cccc{3, } → ccc, cccc, ... |
集合
字元 | 說明 | 範例 |
---|---|---|
[ ] | 代表集合中的任一字元 | [01256] → 0,1,2,5,6 |
- | 在中括號內表示「範圍」(使用ascii計算) | [0-9] → 0, 1, 2, ..., 9 |
^ | 在中括號內表示「否定」 | [^aeiou] → 所有子音(❌); a, e, i, o, u以外的所有字元(✔️) |
| |
或 | cat|dog|bird → cat, dog, bird |
- 容許多個範圍(自動加上或):
[a-zA-Z0-9]
子字串
字元 | 說明 | 範例 |
---|---|---|
(x) | 將x取出,拿取資料時使用 | (a*) and (b*) 可找出「aaa and bb」 中的 「aaa」 和 「bb」 |
(?:x) | 不取出x,純粹當作一個子空間使用 | industr(?:y|ies) → industry, industries |
(?=x) | 正向肯定預查,確認後方的字串是否符合 | Windows(?=95|98|NT|2000) → Windows95(✔️), Windows8(❌) |
(?!x) | 正向否定預查,確認後方的字串是否不符合 | Windows(?!95|98|NT|2000) → Windows95(❌), Windows8(✔️) |
(?<=x) | 反向肯定預查,確認前方的字串是否符合 | (?<=95|98|NT|2000)Windows → 95Windows(✔️), 8Windows(❌) |
(?<!x) | 反向否定預查,確認前方的字串是否符合 | (?<!95|98|NT|2000)Windows → 95Windows(❌), 8Windows(✔️) |
(?) | 不貪心的比對 (不貪心:比對到的字串愈短愈好) |
abc* → ab, abc, abcc... abc*? → ab, abc, abcc都只會match到ab |
\1 | 捕獲分組 | <p id="(\d*)">\1</p> → <p id="123">123</p> (✔️), <p id="123">1234</p> (❌) |
預查即代表不對應,所以最後四個範例都只會回傳符合的Windows
而非Windows95
或Windows8
,而(?:x)
是可以回傳符合的industry
或industries
簡寫
字元 | 說明 | 等價表達 |
---|---|---|
\d | 數字 | [0-9] |
\D | \d以外的字元 | [^0-9] |
\w | 數字、字母、底線 | [a-zA-Z0-9_] |
\W | \w以外的字元 | [^a-zA-Z0-9_] |
\s | 空白字元(tab, 換行等) | [ \t\n\x0B\f\r] |
\S | \s以外的字元 | [^ \t\n\x0B\f\r] |
\n | 換行符號 | |
. | \n以外的字元 | [^\n] |
\b | 英文字的邊界(空格、逗號等符號) | (?<=\W)(?=\w)|(?<=\w)(?=\W) |
\B | \b以外的字元 | (?<=\W)(?=\W)|(?<=\w)(?=\w) |
\x[hex] | 十六進位,其中hex是十六進位數目 | \x38 → $38_{16}$ = 56 |
\u[unicode] | unicode,其中unicode為十六進位數字 | \u00A9 → © |
\c[X] | 控制字元,其中 X 是控制字元 | \cM 可以比對Control-M |
- 特殊字元:有特殊意義的字元,如上述
*
,$
等- 若要搜尋這些字元,必須在其前方加上
\
以跳脫字元(\^
→ ^)
- 若要搜尋這些字元,必須在其前方加上
正規表示式範例
- 數字或無輸入:
^[0-9]*$
- m到n個數字:
^\d{m,n}$
- 正整數(含0):
^0$|^[1-9][0-9]*$
- 用戶密碼 - 以字母開頭,長度在 6~18 之間,只能包含英數字和底線:
^[a-zA-Z]\w{5,17}$
- 漢字:
[\u4e00-\u9fa5]+
- IP位址:
^((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))*$
- 可以先取
^(\d{0,3})\.(\d{0,3})\.(\d{0,3})\.(\d{0,3})$
,再判斷取出的數字在0~255之間即可
- 可以先取
- 可以思考下列兩題,是否有更好的寫法
- 一個月的 31 天(包含01-09和1-31):
^((0?[1-9])|((1|2)[0-9])|30|31)$
- Email:
^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})*$
- 一個月的 31 天(包含01-09和1-31):
例:以grep搜尋檔案內容
- 在當前目錄尋找包含輸出函式
printf
或fprintf
的檔案:grep -Ern 'f?printf' .
-E
使用正規表示式-r
遞迴搜尋(子目錄)-n
列出行數- 加入尋找
sprintf
grep -Ern '[sf]?printf' .
心得
- regex 很像 CFG(Context Free Grammar),應該是可以互相轉換
- 可先使用regex101測試regex是否正確
參考資料
- Wikipedia
- regexp介紹
- 簡易圖片教學
- regexp-轉載自張智星教學網站
- 朱孝國--正規表示式原理及應用
- 鳥哥
- 洪朝貴:字串樣版 Regexp: 兼談長線學習投資
- 常用的正規表示式
- 学习正则表达式