正規表達式(Regular Expression)
首次接觸到正規表達式的時候,簡直看不懂這是什麼鬼,無從下手。學習後發現,其實正規表達式也就類似于數學運算。數學運算中,我們隻要記住數學運算中的+、-、*、/、()等這些數學運算符的規則,再做一些練習,以後讀懂和使用就不成問題了,正規表達式也是如此。是以下面講一下正規表達式中的字元和對應的規則,隻要跟着下面一步一步來,再做一下練習,你會發現正規表達式并沒有那麼難,so easy,以後再也不怕啦。
1、 簡介
正規表達式是一種文本模式,包括普通字元和特殊字元(稱為元字元)。正規表達式使用單個字元串來描述、比對一系列比對某個句法規則的字元串。
也許你已經使用過正規表達式了,比如在使用*或?通配符來查找硬碟上的檔案。比如*.txt就會查找所有以.txt結尾的檔案。
應用:正規表達式在很多應用軟體中都可使用。如Linux、PHP、C#、JAVA等等
2、 文法
正規表達式是由普通字元和特殊字元(即“元字元”)組成的文字模式。
普通字元:大寫字母、小寫字母、數字、标點符号和一些其他符号。(除元字元外的所有可列印和不可列印字元)。
1) 大小寫字母、數字、标點符号(除特殊字元)
2) 非列印字元:
字元 | 描述 |
\cx | 比對由x指明的控制字元,如\cM比對一個control-M或回車符。X必須是字母,否則c視為一個原義的‘c’字元。 |
\f | 換頁符 |
\n | 換行符 |
\r | 回車符 |
\s | 比對任何空白字元,包括空格、制表符、換頁符等。等價于[\f\n\r\t\v] |
\S | 比對任何非空白字元,等價于[^\f\n\r\t\v] |
\t | 制表符 |
\v | 垂直制表符 |
特殊字元:(即“元字元”)就是正規表達式中定義了有特殊含義的字元。
1) 限定符:指定出現次數,限定符有以下6種。
限定符 | 描述 | 例子 |
* | 比對前面的子表達式0次或多次 | zo*能比對z、zoo等。等價于{0,} |
+ | 比對1次或多次 | zo+能比對zo、zoo,不能比對z。等價于{1,} |
? | 比對0次或1次 | zo?能比對z和zo。等價于{0,1} |
{n} n為非負整數 | 比對n次 | zo{2}能比對zoo、zooms等。 |
{n,} n為非負整數 | 最少比對n次 | zo{2,}能比對zoo、zooo、zoooo等。 |
{n,m} nm為非負整數 | 最少比對n次,最多m次 | zo{2,3}能比對zoo、zooo。注意逗号之間不要有空格。 |
練習:
正規表達式 | 描述 |
/Chapter [1-9][0-9]*/ | [1-9]表示1-9中的任一數字可以出現一次 [0-9]*表示0-9中的任意數字可以出現0次或多次 |
/Chapter [1-9][0-9]?/或 /Chapter [1-9][0-9]{0,1}/ | 表示隻比對兩位數字的章節。 |
貪婪與非貪婪:*、+、?限定符是貪婪的,在它們後面加上?就是非貪婪的。
貪婪:在所有内容中比對,直到所有内容中沒有比對成功的内容為止。
非貪婪:在内容中從頭開始比對,在遇到第一個比對不成功的即停止。而貪婪是比對到所有内容。
如:字元串内容是<h1>12345<h1>,貪婪/<.*>/,會比對到<h1>12345<h1>;非貪婪/<.*?>/會比對到<h1>。
2) 定位符:顧名思義,定位符即可以辨別正規表達式的位置,如行首、行尾、邊界。
定位符 | 描述 | 例子 |
^ | 1. 辨別是字元串開始的位置。 2. 在中括号裡[^],表示排除指定字元外。 | /^Chapter/指一定是Chapter開頭的 [^abc]即不包含有字元abc的 |
$ | 辨別是字元串結束的位置 | /[0-9]+$/指一定是數字結尾的 |
\b | 辨別字邊界,即字與空格間的位置 | /\bCha/指Cha是一個字的開頭 /ter\b/指ter是一個字的結尾 |
\B | 非字邊界比對,即在字的中間位置,非首尾。 | /\Bapt/能比對Chapter,不能比對aptude,因為在aptude中是字首。 |
3) 選擇:用()括起來,相鄰的選擇項之間用|分隔。即“或”的關系。
在正規表達式中,()會把括号内相關的比對緩存起來(緩存以便反向引用)。
此時可以使用非捕獲元(有三種?:、?=、?!)來取消緩存。如:/(hello|hi)/能比對helloworld、hiworld等,但會緩存hello和hi;而/(?:hello|hi)/能實作同樣的比對規則,而且不會緩存。
4) 反向引用:就是可以在緩存中進行選擇比對。在查找文本中兩個相同的相鄰單詞時就需要用到反向引用。
()内的比對會被按順序存儲到臨時緩沖區,且賦予編号1-99(最大99)。通過\num通路緩沖區(其中num表示1-99的數字)。例:
Is is the cost of of gasoline going up up?句子中有重複單詞,現在設法找出重複的單詞并且隻保留重複單詞中的第一個。如:/b([a-z]+) \1\b/gi。其中\1表示指定第一個子比對項。i标示忽略大小寫。g是全局标記,将表達式應用到輸入字元串中能夠查找到的盡可能多的比對項。
5) 非捕獲元
字元 | 描述 | 例子 |
(?:pattern) | 比對pattern但不擷取結果;不存儲。 | ‘industr(?:y|ies)’就是一個比’industry|industries’更簡略的表達式。但技術實作本身是一樣的。 |
(?=pattern) | 正向預查,在任何比對pattern的字元串開始的位置比對查找字元串;不存儲。 | ‘windows(?=95|98)’在一次比對發生後,在最後一次比對之後立即開始下一次比對的搜尋,而不是從包含預查的字元之後開始。 |
(?!pattern) | 負向預查,在任何不比對pattern的字元串開始的位置比對查找字元串;不存儲。 | ‘windows(?=95|98)’能比對window3.1中的windows,而不能比對windows95中的windows。同?=從最後一次比對之後開始下一次比對的搜尋。 |
6) 其他元字元
字元 | 描述 | 例子 |
\ | 轉義。将下一個字元标記為特殊字元或原義字元或向後引用或八進制轉義符 | ‘n’比對字元n,’\n’則比對一個換行符 |
. | 除換行符’\n’之外的任何單個字元 | 若要包含’\n’,需使用“(.|\n)” |
x|y | 比對字元x或y | ‘z|food’能比對z或food |
[xyz] | 字元集合。比對所包含的任意一個字元。 | ‘{abc}’可以比對‘plain’中的a |
[^xyz] | 負值字元集合。比對未包含的任意字元 | ‘{abc}’可以比對‘plain’中的p、l、i、n。 |
[a-z] | 字元範圍。指定範圍内的任意字元 | [a-z]可以比對任何不在a到z範圍内的任意字元。 |
\d | 比對一個數字字元 | 等價于[0-9] |
\D | 比對一個非數字字元 | 等價于[^0-9] |
\w | 比對任何非單詞字元 | 等價于[^a-zA-Z0-9_] |
\xn | 比對n,n為十六進制轉義符。 | \x41比對A |
\num | Num是正整數。對所擷取的比對的引用 | (.)\1比對兩個連續的相同字元 |
\n | 辨別一個八進制轉義值或一個向後引用 | |
\nm | ||
\nml | ||
\un |
3、 運算符優先級:同數學運算符一樣,運算符有固定的優先級,以下為運算符優先級順序:
運算符 | 描述 |
\ | 轉義符 |
()、(?:)、(?=)、[] | 圓括号和方括号 |
*、+、? 、{n}、{n,} 、{n,m} | 限定符 |
^、$、\任何元字元、任何字元 | 定位符和序列(即位置和順序) |
| | 替換,“或”操作 |
4、 練習
題目 | 答案 |
比對所有小寫字母 | [a-z] |
所有字母和下劃線 | [A-Za-z_] |
比對所有的數字 | [0-9] |
比對所有的數字、句号和減号 | [0-9\.\-] |
比對所有的白字元 | [ \f\r\t\n] |
比對 一個小寫字母和一位數字組成的字元串 | ^[a-z][0-9]$ |
除了小寫字母以外的所有字元 | [^a-z] |
除了‘\’、‘/’、‘^’以外的所有字元 | [^\\\/\^] |
字母a | ^a$ |
2-4個字母a | ^a{2,4}$ |
包含2或多于2個a的字元串 | ^a{2,}$ |
兩個制表符 | \t{2} |
所有的兩個字元 | .{2} |
所有包含一個以上的字母、數字或下劃線的字元串 | ^[A-Za-z0-9_]+$ |
所有的正整數 | ^[1-9][0-9]*& |
0及所有的正整數 | ^[0-9]*& |
所有的浮點數 | ^\-?[0-9]+\.?[0-9]*& |
一個單詞連續出現的位置 | \b([a-z]+) \1\b/gi |
将一個URL解析為協定、域、端口及相對路徑 http://www.baidu.com:80/aaa.bbb.ccc | /(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)/ |
定位章節的位置 | /^(?:Chapter|Section) [1-9][0-9]*$/ |
a至z共26個字母再加一個-号 | /[-a-z]/ |
可比對chapter但不能比對aptitude | /ter\b/ |
5、 工具
工具:RegexBuddy 3
線上工具: https://c.runoob.com/front-end/854
轉自:http://www.runoob.com/regexp/regexp-tutorial.html
還有個很棒的入門文檔:http://www.92csz.com/regex/