- 浏览: 74385 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
godownget:
三大主流数据库神速上手(MySQL、MSSQL、Oracle) ...
WebSphere中流行数据库连接池的配置(Oracle、SQL Server、Sybase、MySQL) -
guoweihelloworld:
[b]: [引用b]文字 (alt+b)[/b][/b]htt ...
Struts-Menu结合角色权限的应用 -
fjkzn1102:
能否给个例子看看,正在学习这方面的集成开发
SSH JBPM ACEGI JBPM WEB CONSOLE -
liyingxu30:
非常感谢非常感谢非常感谢非常感谢非常感谢非常感谢非常感谢非常感 ...
WebSphere中流行数据库连接池的配置(Oracle、SQL Server、Sybase、MySQL) -
zhuqx1130:
securityContextHolderAwareReque ...
Struts-Menu结合角色权限的应用
雖然Reqular
Expressions(以下簡稱REs)在這個論壇或是其他網站都可以找到相當多的資料,但是當我自己要學的時候才發現有很多小地方還是看不懂,所以才
以java API裡面的說明為主,把每個符號的解釋一一弄懂,終於對REs有了初步的認識。
所以這份文件是以java API提到的符號解釋,加上我自己的心得及範例所整理出來的,我用"字元"和"字元組成",這兩大部分來解釋REs的符號,大部分的解釋都有範例,這樣比 較容易瞭解,沒有範例的部分不是太簡單,就是我找不到例子,不過對於認識REs應該沒有多大影響。
因為我算是REs的初學者,所以難免有觀念上的錯誤,加上很多"冷門"的符號,要找到正確的解釋都很困難,因此我沒把握所有的資料都是正確的,如果各位有發現錯誤,還請加以指正。
首先是字元,REs的基本元素就是字元,所以對於字元有相當細膩的描述方式,而且很多時候描述方式都不是唯一的,所以不必拘泥於找到最完美的寫法。
字元分兩部分來解釋。
1.一般字元,在還沒做字元組合時,下面這些都只是"一個"字元,先要有這個觀念,才不容易弄不清楚字串和字元的區別。
x : 一個字元,例如 "a" 表示要找含有這個字元的部分。
[abc] : 這個字元可能是a或b或c
[^abc] : 這個字元是除了"a" "b" "c"以外的。
[a-zA-Z] : 這個字元是a到z或是A到Z。
[a-d[m-p]] : 這個字元是a到d或是m到p (聯集)。
[a-z&&[def]] : 這個字元是"d", "e", or "f" (交集)。
[a-z&&[^bc]] : 這個字元是a-z但b c 除外,等價於 [ad-z] (差集)。
[a-z&&[^m-p]] : 這個字元是a-z但 m-p 除外,等價於 [a-lq-z] (差集)。
除了放在一開始的"^"以及兩個"&&"以外,放在[]裡面的都當一般字元。
可是\比較特殊,要\\才能當一個\,所以程式裡面必須寫\\\\,例如,想查"\"用[]包起來要寫成"[\\]",可是java在字串裡面要寫String pattern="[\\\\]"。
2.特殊字元. : 所有的字元,不一定包含換行。java REs的"."預設是不包含"\r"和"\n"的,但是可以用(?s)來讓"."等於所有字元,(?s)的用法下面還有說明。
\r : Carriage return。
\t : TAB。
\n : 換行。
\f : 換頁。
\e : escape。
\d : 數字0-9。
\D : 非數字,數字的除外集合。
\s : 會產生空白的字元也就是 [ \t\n\x0B\f\r],也就是 " "(空白)、"\t"、"\n"、"\x0B"、"\f"、"\r"。
\S : 非會產生空白的字元,上面的除外集合。
\w : 文字 a-z A-Z _ 0-9,所有的英文大小寫,數字和底線。
\W : 非文字,文字的除外集合。
\ : 把之後的特殊字元當作是一般是字元,例如"\\"等於一個"\","\["等於"["。
\Q \E:\Q到\E符號之間的特殊符號都當一般字元處理,例如"\Q(?:X)\E",符合的字串是"(?:X)"
^ : 行首,例如"^e"會找出所有在行首的"e",在[]裡面如果是第一個代表反相,如果不是第一個也當一般字元。
$ : 行尾,例如"e$"會找出所有在結尾的"e"。
\b : 符合文字邊界(word boundary)。也就是說在字與空格之間的位置 例如,'re\b' 符合"are" 裡的're'但是不符合"area"裡的're'
\B : 符合非文字邊界 例如,'re\B' 符合"area"裡的're'但是不符合"are" 裡的're'
\A : 輸入的開始。
\G : 前一個符合的結尾的地方。
\Z : 輸入的結尾去掉結尾符號的部分。例如字串"ABC\n",pattern "ABC\Z"就可以取得"ABC"。
\z : 輸入的結尾。例如字串"ABC\n",pattern "ABC\z"就不相符。
所謂的輸入,是指一次的處理資料,例如String s="ABC\nABC\tABC",就算一個輸入(input sequence)。
到這裡為止是對字元的描述,字元的所有的可能情況應該都可以涵蓋了,可是光是字元是沒辦法構成字串,所以接下來是把字元組成字串的方法。
字元組成,字元組成分三部分來解釋,下面符號的X和Y可以是一個字元也可以是一個Group。
1.簡單組合,就是把字元排在一起。
XY : 單純排列在一起,例如"ab"就是找"ab"這個字串,和"[ab]"不一樣,"[ab]"是代表"一個字元"可能是a或b。
X|Y : X or Y,例如 a|b,而以字元而言a|b就等於[ab],所以對單一字元效果不大,主要是用於字元範圍的[]|[]或者群組()|()比較有意義。
例如[a-z]|[0-9]表示不是小寫就是數字,(abc)|(123)表示是"abc"或是"123"。
實例 "c|Car"(等同於"[cC]ar")相符字串是"car"或"Car"。<-錯了,下面有被糾正的說明,所以就不改這裡。
另外abc|def是指"abc"或"def",而不是"ab[cd]ef"。
(X) : 群組,將多個字元包裝成一個群組,和單純排列不同的地方是,群組可以參照,也可以對群組設定出現次數,
例如(abc)+是指"abc"出現一次以上,abc+是指ab和一次以上的c。
群組參照舉例來說比較容易懂,例如"(.)(.)(.).?\3\2\1",可以找出3個字的回文。如"abccba"、"xcdfdcx"。
群組還有一個值得注意的是,群組0是留給整體的比對的結果,例如上面的例子group 0是"abccba",group 1是"a"、group 2是"b"、group 3是"c"。
有了群組參照的觀念,後面的non-capturing group就會比較容易瞭解。。
Group的另一個對應符號是
\m : m是數字,表示參照前面的group,如上述的範例。
2.重複次數
出現次數接在字元之後,表示這個字元出現的次數,接在Group之後就表示group的出現次數。
次數描述有三種quantifiers,
Greedy quantifiers
X?: X出現0或一次
X+: X出現一次以上
X*: X出現0或一次以上
X{n,}: X出現至少n次
X{n,m}: X出現n到m次
X{n}: X出現n次
Reluctant quantifiers
X??: X出現0或一次
X+?: X出現一次以上
X*?: X出現0或一次以上
X{n,}?: X出現至少n次
X{n,m}?: X出現n到m次
X{n}?: X出現n次
Possessive quantifiers
X?+: X出現0或一次
X++: X出現一次以上
X*+: X出現0或一次以上
X{n,}+: X出現至少n次
X{n,m}+: X出現n到m次
X{n}+: X出現n次
光看這樣的說明是無法分出三者不同,以下舉例說明。
Greedy quantifiers
字串 "xfooxxxxxxfoo"
pattern ".*foo"
結果 xfooxxxxxxfoo
Greedy字面翻譯是貪婪,也就是盡可能的取字串,其實最貪婪的是第三種方法,因為Greedy還會把之後相符的資料留下來,Possessive吃的連骨頭都不剩。
Reluctant quantifiers
字串 "xfooxxxxxxfoo"
pattern ".*?foo"
結果 xfoo 和 xxxxxxfoo
Reluctant字面翻譯是勉強,也就是抓最小可能,像這個例子,第一次抓一個x之後發現後面和foo相符,就得第一個結果,然後一直到最後又得到第二個結果。
Possessive quantifiers
字串 "xfooxxxxxxfoo"
pattern ".*+foo"
結果 沒有相符合資料,因為所有的資料都與"."比較相符,最後沒有剩下的字串可以和foo做比較,所以沒有符合資料。
3.Special constructs (non-capturing)
所謂的non-capturing就是說這個group會被比對,但是不會暫存在group裡面,就是最後得到的Group裡面不會有這組資料。
(?:X) :X會取得,但不會被保留,當之後有用\m的時候,這個Group會不算在內,這樣的處理效能會比較好。
(?i d m s u x) : 特別設定的flag設為on。
(?-i -d -m -s -u -x) : 特別設定的flag設為off。
i d m s u x的說明如下:
i CASE_INSENSITIVE : 就是不分大小寫。(?i)
例如
字串 "ABC"
pattern 用"abc"會找不到,用"(?i)abc"就會找到"ABC"。
d UNIX_LINES : \n當作換行,當文件是UNIX的換行格式時,要處理換行就可以打開這個模式。(?d)
m MULTILINE :多行模式下,^和$是以指每一行,不然是用整個字串的頭尾當^和$。(?m)
例如
字串 "ABC\nABC\nABC";
pattern "^ABC$"會找不到, "(?m)^ABC$"才會找到三個"ABC";
s DOTALL : 預設java的.不含\n \r,這個模式可以讓.等於所有字元包含\r \n。(?s)
例如
字串 "htm\nhtm\nhtm"
pattern 用".htm"會找不到,用"(?s).htm"就會找到後面兩個"\nhtm"
u UNICODE_CASE : unicode模式。(?u)
x COMMENTS :可以在pattern裡面使用註解,會忽略pattern裡面的whitespace,以及"#"一直到結尾。(?x)
例如
字串 "ABC"
pattern 用"A B C #找字串ABC" 會找不到,用"(?x)A B C #找字串ABC",就會找到"ABC"。
(?idmsux-idmsux:X) :X是non-capturing group並且設定flags on -off。
X(?=X) : lookahead在要取得的字串右邊,接著X但X不被算在內。例如Jack(?=Sprat) 則只有JackSprat的Jack會被取得,Jack(?=Sprat|Frost),則只有JackSprat和JackFrost的Jack都符合。
X(?!X) : lookahead在要取得的字串右邊,和上面相反,例如Jack(?!Sprat) 則後面是Sprat的Jack不會被取得。
(?<=X)X : lookbehind在要取得的字串左邊,例如"(?<=foo)bar",找接在foo之後的"bar"。還有裡面的文字必須已知長度,也就是不 能用"(?<=foo+)" "(?<=foo*)" "(?<=foo{1,})",但是可以用"(?<=foo?)" "(?<=foo{1,2})" "(?<=foo{1})"。
(?<!X)X : lookbehind在要取得的字串左邊,例如"(?<!foo)bar",找不是接在foo之後的"bar"。關於長度和上面符號有相同限制。
(?>X) : X, as an independent, non-capturing group。
因為這幾個符號都是non-capturing的,所以會有一個現象,直接看下面範例會比較容易瞭解
字串 "abc"
pattern "a(?:b)c"
結果 "abc" 但是b沒有變成group 1,這也就是non-capturing。
如果用 "a(b)c" 會得到 group 0是"abc",group 1是b。
字串 "abc"
pattern "a(?=b)c"
結果 抓不到,因為b並沒有被取出,要"a(?=b).c"才抓的到,而且"a(?=b).c"只會與"abc"相符,不會與"acc"等等相符。
字串 "abc"
pattern "a(?<=b)c"
結果 抓不到,因為b並沒有被取出,要"a.(?<=b)c"才抓的到,而且"a(?<=b).c"只會與"abc"相符,不會與"acc"等等相符。
由上面例子可知,這幾個符號都不會把符合的字串取出,也就是會比對但是不會算到結果裡面(non-capturing)。
所以lookahead和lookbehind那四個符號,不適合放在字串中間,另外,因為這幾個符號都是non-capturing,所以在後 面加上大於0的次數都和一次是一樣的,例如字串"XB",pattern"(?<=X){9}B"一樣可以取得B,而pattern""(? <=A){0}B"也可以取得"B"。
整個java的REs大概就這些了,只是看完這些解釋其實離可以運用還有一小段距離,因為REs需要的是分析pattern的能力,而這種能力要多練習才會。
在自己能寫出pattern之前,可以拿別人寫好的pattern來測試體會一下,下面是一個簡單的測試程式。
這個程式是我小修改網路上找到的範例,會回傳符合的group,方便測試結果。
測試REs也可以使用一外部工具,例如eclipse的plugin Regex tester,我很多範例跟觀念都是用這個工具去測試的。
最後"反組譯"幾個例子來練習,就是把別人寫好的pattern試著解釋出來。
HTML TAG
</?[a-z][a-z0-9]*[^<>]*>
開始是<,接著有0或1個/,接著是一個英文字,再接著是不限次數的英文或數字,之後是非"<"或">"的字元不限次數個,最後以">"結尾。
相符的是"<html>" "</html>" "<h0>"等。
不相符字串 "<123>"
HTML TAG 之二
<([A-Z][A-Z0-9]*)[^>]*>(.*?)</\1>
開始是<,然後由一個大寫英文字,和不限定個數的數字或大寫字母,構成一個group,接著不限個數的非">"字元,然後是一個 ">",不限定個數的字元(用*?才不會一直取到之後的tag去),然後是tag結束的"</",要和第一個Group的值match,最後 以">"結束。
相符的有 "<A HREF="www.google.com.tw">Test</A>" "<P></P> "<PRE>Test</PRE>" "<H0></H0>"
不相符字串 "<abc></def>" "<123></123>"
IP
\b(?:(?: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]?)\b
前後都是"\b"表示在獨立的一個字的單元,用"?:"是不算group而已,250-255或200-249或0-199,接著一個".",這樣的group有3次,最後再一次0-255的group。
這樣就是一個0.0.0.0 - 255.255.255.255的IP的pattern,而[0-9][0-9]?也可以改成[0-9]{1,2}。
相符的字串 "140.115.83.240" "255.255.0.0"
不相符字串 "256.1.1.2" "-1.300.1.2"
IP之二
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
IP之三
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
這是0.0.0.0 - 999.999.999.999的格式
其他例子
"[hc]+at" 相符的有 "hat", "cat", "hhat", "chat", "hcat", "ccchat" etc.
"[hc]?at" 相符的有 "hat", "cat" and "at"
"([cC]at)|([dD]og)" 相符的有 "cat", "Cat", "dog" and "Dog"
"/\*.*\*/" 相符的有 /* Second comment */
以下幾個(都是抄的)適合檢查輸入的值,因為都從^到$,從字串開始到結束。
1、非負整數:”^\d+$”
2、正整數:”^[0-9]*[1-9][0-9]*$”
3、非正整數:”^((-\d+)|(0+))$”
4、負整數:”^-[0-9]*[1-9][0-9]*$”
5、整數:”^-?\d+$”
6、非負浮點數:”^\d+(\.\d+)?$”
7、正浮點數:”^((0-9)+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$”
8、非正浮點數:”^((-\d+\.\d+)?)|(0+(\.0+)?))$”
9、負浮點數:”^(-((正浮點數正則式)))$”
10、英文字符串:”^[A-Za-z]+$”
11、英文大寫串:”^[A-Z]+$”
12、英文小寫串:”^[a-z]+$”
13、英文字符數字串:”^[A-Za-z0-9]+$”
14、英數字加下劃線串:”^\w+$”
15、E-mail地址:”^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$”
16、URL:”^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$”
-------
學習REs最重要是學會找到字串出現的特徵,特徵有時候是出現的位置,例如位置是行首(^),是行尾($),單字開始(\b),單字裡面(\ B),有時候是前後出現的字串,例如要找html tag的屬性,都會由"<"當開始,到">"結束。而要抓"<a>"的url就可以從"href"開始。但有時候要找的字並沒有 特殊的位置,也沒關係,就把要找的字描述出來也就可以了,例如要抓日期就做一個"(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)[0-9]{2}"的pattern就可以了。
而其實真正困難的地方在於很多pattern都要看到結果才會瞭解哪裡錯了。
看這個例子
字串 "ABCDC"
pattern "([A-Z]*).\1"
預期要抓到CDC的,結果卻是"A" "B" "CDC",因為*是0~n所以沒抓也算,而後面的\1如果前面group沒抓到,他也跟著什麼都沒有,最後只有"."抓到第一個結果的"A",同理抓到 第二個結果的"B",然後才抓到預期的"CDC",而改成"([A-Z]+).\1"就只會抓到"CDC"了。
最後誰能幫忙解釋一下"(?>X)",因為我實在分不出來他和(?:X)有什麼差別....
所以這份文件是以java API提到的符號解釋,加上我自己的心得及範例所整理出來的,我用"字元"和"字元組成",這兩大部分來解釋REs的符號,大部分的解釋都有範例,這樣比 較容易瞭解,沒有範例的部分不是太簡單,就是我找不到例子,不過對於認識REs應該沒有多大影響。
因為我算是REs的初學者,所以難免有觀念上的錯誤,加上很多"冷門"的符號,要找到正確的解釋都很困難,因此我沒把握所有的資料都是正確的,如果各位有發現錯誤,還請加以指正。
首先是字元,REs的基本元素就是字元,所以對於字元有相當細膩的描述方式,而且很多時候描述方式都不是唯一的,所以不必拘泥於找到最完美的寫法。
字元分兩部分來解釋。
1.一般字元,在還沒做字元組合時,下面這些都只是"一個"字元,先要有這個觀念,才不容易弄不清楚字串和字元的區別。
x : 一個字元,例如 "a" 表示要找含有這個字元的部分。
[abc] : 這個字元可能是a或b或c
[^abc] : 這個字元是除了"a" "b" "c"以外的。
[a-zA-Z] : 這個字元是a到z或是A到Z。
[a-d[m-p]] : 這個字元是a到d或是m到p (聯集)。
[a-z&&[def]] : 這個字元是"d", "e", or "f" (交集)。
[a-z&&[^bc]] : 這個字元是a-z但b c 除外,等價於 [ad-z] (差集)。
[a-z&&[^m-p]] : 這個字元是a-z但 m-p 除外,等價於 [a-lq-z] (差集)。
除了放在一開始的"^"以及兩個"&&"以外,放在[]裡面的都當一般字元。
可是\比較特殊,要\\才能當一個\,所以程式裡面必須寫\\\\,例如,想查"\"用[]包起來要寫成"[\\]",可是java在字串裡面要寫String pattern="[\\\\]"。
2.特殊字元. : 所有的字元,不一定包含換行。java REs的"."預設是不包含"\r"和"\n"的,但是可以用(?s)來讓"."等於所有字元,(?s)的用法下面還有說明。
\r : Carriage return。
\t : TAB。
\n : 換行。
\f : 換頁。
\e : escape。
\d : 數字0-9。
\D : 非數字,數字的除外集合。
\s : 會產生空白的字元也就是 [ \t\n\x0B\f\r],也就是 " "(空白)、"\t"、"\n"、"\x0B"、"\f"、"\r"。
\S : 非會產生空白的字元,上面的除外集合。
\w : 文字 a-z A-Z _ 0-9,所有的英文大小寫,數字和底線。
\W : 非文字,文字的除外集合。
\ : 把之後的特殊字元當作是一般是字元,例如"\\"等於一個"\","\["等於"["。
\Q \E:\Q到\E符號之間的特殊符號都當一般字元處理,例如"\Q(?:X)\E",符合的字串是"(?:X)"
^ : 行首,例如"^e"會找出所有在行首的"e",在[]裡面如果是第一個代表反相,如果不是第一個也當一般字元。
$ : 行尾,例如"e$"會找出所有在結尾的"e"。
\b : 符合文字邊界(word boundary)。也就是說在字與空格之間的位置 例如,'re\b' 符合"are" 裡的're'但是不符合"area"裡的're'
\B : 符合非文字邊界 例如,'re\B' 符合"area"裡的're'但是不符合"are" 裡的're'
\A : 輸入的開始。
\G : 前一個符合的結尾的地方。
\Z : 輸入的結尾去掉結尾符號的部分。例如字串"ABC\n",pattern "ABC\Z"就可以取得"ABC"。
\z : 輸入的結尾。例如字串"ABC\n",pattern "ABC\z"就不相符。
所謂的輸入,是指一次的處理資料,例如String s="ABC\nABC\tABC",就算一個輸入(input sequence)。
到這裡為止是對字元的描述,字元的所有的可能情況應該都可以涵蓋了,可是光是字元是沒辦法構成字串,所以接下來是把字元組成字串的方法。
字元組成,字元組成分三部分來解釋,下面符號的X和Y可以是一個字元也可以是一個Group。
1.簡單組合,就是把字元排在一起。
XY : 單純排列在一起,例如"ab"就是找"ab"這個字串,和"[ab]"不一樣,"[ab]"是代表"一個字元"可能是a或b。
X|Y : X or Y,例如 a|b,而以字元而言a|b就等於[ab],所以對單一字元效果不大,主要是用於字元範圍的[]|[]或者群組()|()比較有意義。
例如[a-z]|[0-9]表示不是小寫就是數字,(abc)|(123)表示是"abc"或是"123"。
實例 "c|Car"(等同於"[cC]ar")相符字串是"car"或"Car"。<-錯了,下面有被糾正的說明,所以就不改這裡。
另外abc|def是指"abc"或"def",而不是"ab[cd]ef"。
(X) : 群組,將多個字元包裝成一個群組,和單純排列不同的地方是,群組可以參照,也可以對群組設定出現次數,
例如(abc)+是指"abc"出現一次以上,abc+是指ab和一次以上的c。
群組參照舉例來說比較容易懂,例如"(.)(.)(.).?\3\2\1",可以找出3個字的回文。如"abccba"、"xcdfdcx"。
群組還有一個值得注意的是,群組0是留給整體的比對的結果,例如上面的例子group 0是"abccba",group 1是"a"、group 2是"b"、group 3是"c"。
有了群組參照的觀念,後面的non-capturing group就會比較容易瞭解。。
Group的另一個對應符號是
\m : m是數字,表示參照前面的group,如上述的範例。
2.重複次數
出現次數接在字元之後,表示這個字元出現的次數,接在Group之後就表示group的出現次數。
次數描述有三種quantifiers,
Greedy quantifiers
X?: X出現0或一次
X+: X出現一次以上
X*: X出現0或一次以上
X{n,}: X出現至少n次
X{n,m}: X出現n到m次
X{n}: X出現n次
Reluctant quantifiers
X??: X出現0或一次
X+?: X出現一次以上
X*?: X出現0或一次以上
X{n,}?: X出現至少n次
X{n,m}?: X出現n到m次
X{n}?: X出現n次
Possessive quantifiers
X?+: X出現0或一次
X++: X出現一次以上
X*+: X出現0或一次以上
X{n,}+: X出現至少n次
X{n,m}+: X出現n到m次
X{n}+: X出現n次
光看這樣的說明是無法分出三者不同,以下舉例說明。
Greedy quantifiers
字串 "xfooxxxxxxfoo"
pattern ".*foo"
結果 xfooxxxxxxfoo
Greedy字面翻譯是貪婪,也就是盡可能的取字串,其實最貪婪的是第三種方法,因為Greedy還會把之後相符的資料留下來,Possessive吃的連骨頭都不剩。
Reluctant quantifiers
字串 "xfooxxxxxxfoo"
pattern ".*?foo"
結果 xfoo 和 xxxxxxfoo
Reluctant字面翻譯是勉強,也就是抓最小可能,像這個例子,第一次抓一個x之後發現後面和foo相符,就得第一個結果,然後一直到最後又得到第二個結果。
Possessive quantifiers
字串 "xfooxxxxxxfoo"
pattern ".*+foo"
結果 沒有相符合資料,因為所有的資料都與"."比較相符,最後沒有剩下的字串可以和foo做比較,所以沒有符合資料。
3.Special constructs (non-capturing)
所謂的non-capturing就是說這個group會被比對,但是不會暫存在group裡面,就是最後得到的Group裡面不會有這組資料。
(?:X) :X會取得,但不會被保留,當之後有用\m的時候,這個Group會不算在內,這樣的處理效能會比較好。
(?i d m s u x) : 特別設定的flag設為on。
(?-i -d -m -s -u -x) : 特別設定的flag設為off。
i d m s u x的說明如下:
i CASE_INSENSITIVE : 就是不分大小寫。(?i)
例如
字串 "ABC"
pattern 用"abc"會找不到,用"(?i)abc"就會找到"ABC"。
d UNIX_LINES : \n當作換行,當文件是UNIX的換行格式時,要處理換行就可以打開這個模式。(?d)
m MULTILINE :多行模式下,^和$是以指每一行,不然是用整個字串的頭尾當^和$。(?m)
例如
字串 "ABC\nABC\nABC";
pattern "^ABC$"會找不到, "(?m)^ABC$"才會找到三個"ABC";
s DOTALL : 預設java的.不含\n \r,這個模式可以讓.等於所有字元包含\r \n。(?s)
例如
字串 "htm\nhtm\nhtm"
pattern 用".htm"會找不到,用"(?s).htm"就會找到後面兩個"\nhtm"
u UNICODE_CASE : unicode模式。(?u)
x COMMENTS :可以在pattern裡面使用註解,會忽略pattern裡面的whitespace,以及"#"一直到結尾。(?x)
例如
字串 "ABC"
pattern 用"A B C #找字串ABC" 會找不到,用"(?x)A B C #找字串ABC",就會找到"ABC"。
(?idmsux-idmsux:X) :X是non-capturing group並且設定flags on -off。
X(?=X) : lookahead在要取得的字串右邊,接著X但X不被算在內。例如Jack(?=Sprat) 則只有JackSprat的Jack會被取得,Jack(?=Sprat|Frost),則只有JackSprat和JackFrost的Jack都符合。
X(?!X) : lookahead在要取得的字串右邊,和上面相反,例如Jack(?!Sprat) 則後面是Sprat的Jack不會被取得。
(?<=X)X : lookbehind在要取得的字串左邊,例如"(?<=foo)bar",找接在foo之後的"bar"。還有裡面的文字必須已知長度,也就是不 能用"(?<=foo+)" "(?<=foo*)" "(?<=foo{1,})",但是可以用"(?<=foo?)" "(?<=foo{1,2})" "(?<=foo{1})"。
(?<!X)X : lookbehind在要取得的字串左邊,例如"(?<!foo)bar",找不是接在foo之後的"bar"。關於長度和上面符號有相同限制。
(?>X) : X, as an independent, non-capturing group。
因為這幾個符號都是non-capturing的,所以會有一個現象,直接看下面範例會比較容易瞭解
字串 "abc"
pattern "a(?:b)c"
結果 "abc" 但是b沒有變成group 1,這也就是non-capturing。
如果用 "a(b)c" 會得到 group 0是"abc",group 1是b。
字串 "abc"
pattern "a(?=b)c"
結果 抓不到,因為b並沒有被取出,要"a(?=b).c"才抓的到,而且"a(?=b).c"只會與"abc"相符,不會與"acc"等等相符。
字串 "abc"
pattern "a(?<=b)c"
結果 抓不到,因為b並沒有被取出,要"a.(?<=b)c"才抓的到,而且"a(?<=b).c"只會與"abc"相符,不會與"acc"等等相符。
由上面例子可知,這幾個符號都不會把符合的字串取出,也就是會比對但是不會算到結果裡面(non-capturing)。
所以lookahead和lookbehind那四個符號,不適合放在字串中間,另外,因為這幾個符號都是non-capturing,所以在後 面加上大於0的次數都和一次是一樣的,例如字串"XB",pattern"(?<=X){9}B"一樣可以取得B,而pattern""(? <=A){0}B"也可以取得"B"。
整個java的REs大概就這些了,只是看完這些解釋其實離可以運用還有一小段距離,因為REs需要的是分析pattern的能力,而這種能力要多練習才會。
在自己能寫出pattern之前,可以拿別人寫好的pattern來測試體會一下,下面是一個簡單的測試程式。
這個程式是我小修改網路上找到的範例,會回傳符合的group,方便測試結果。
1 | import java.util.regex.Matcher; |
測試REs也可以使用一外部工具,例如eclipse的plugin Regex tester,我很多範例跟觀念都是用這個工具去測試的。
最後"反組譯"幾個例子來練習,就是把別人寫好的pattern試著解釋出來。
HTML TAG
</?[a-z][a-z0-9]*[^<>]*>
開始是<,接著有0或1個/,接著是一個英文字,再接著是不限次數的英文或數字,之後是非"<"或">"的字元不限次數個,最後以">"結尾。
相符的是"<html>" "</html>" "<h0>"等。
不相符字串 "<123>"
HTML TAG 之二
<([A-Z][A-Z0-9]*)[^>]*>(.*?)</\1>
開始是<,然後由一個大寫英文字,和不限定個數的數字或大寫字母,構成一個group,接著不限個數的非">"字元,然後是一個 ">",不限定個數的字元(用*?才不會一直取到之後的tag去),然後是tag結束的"</",要和第一個Group的值match,最後 以">"結束。
相符的有 "<A HREF="www.google.com.tw">Test</A>" "<P></P> "<PRE>Test</PRE>" "<H0></H0>"
不相符字串 "<abc></def>" "<123></123>"
IP
\b(?:(?: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]?)\b
前後都是"\b"表示在獨立的一個字的單元,用"?:"是不算group而已,250-255或200-249或0-199,接著一個".",這樣的group有3次,最後再一次0-255的group。
這樣就是一個0.0.0.0 - 255.255.255.255的IP的pattern,而[0-9][0-9]?也可以改成[0-9]{1,2}。
相符的字串 "140.115.83.240" "255.255.0.0"
不相符字串 "256.1.1.2" "-1.300.1.2"
IP之二
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
IP之三
[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
這是0.0.0.0 - 999.999.999.999的格式
其他例子
"[hc]+at" 相符的有 "hat", "cat", "hhat", "chat", "hcat", "ccchat" etc.
"[hc]?at" 相符的有 "hat", "cat" and "at"
"([cC]at)|([dD]og)" 相符的有 "cat", "Cat", "dog" and "Dog"
"/\*.*\*/" 相符的有 /* Second comment */
以下幾個(都是抄的)適合檢查輸入的值,因為都從^到$,從字串開始到結束。
1、非負整數:”^\d+$”
2、正整數:”^[0-9]*[1-9][0-9]*$”
3、非正整數:”^((-\d+)|(0+))$”
4、負整數:”^-[0-9]*[1-9][0-9]*$”
5、整數:”^-?\d+$”
6、非負浮點數:”^\d+(\.\d+)?$”
7、正浮點數:”^((0-9)+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$”
8、非正浮點數:”^((-\d+\.\d+)?)|(0+(\.0+)?))$”
9、負浮點數:”^(-((正浮點數正則式)))$”
10、英文字符串:”^[A-Za-z]+$”
11、英文大寫串:”^[A-Z]+$”
12、英文小寫串:”^[a-z]+$”
13、英文字符數字串:”^[A-Za-z0-9]+$”
14、英數字加下劃線串:”^\w+$”
15、E-mail地址:”^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$”
16、URL:”^[a-zA-Z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\s*)?$”
-------
學習REs最重要是學會找到字串出現的特徵,特徵有時候是出現的位置,例如位置是行首(^),是行尾($),單字開始(\b),單字裡面(\ B),有時候是前後出現的字串,例如要找html tag的屬性,都會由"<"當開始,到">"結束。而要抓"<a>"的url就可以從"href"開始。但有時候要找的字並沒有 特殊的位置,也沒關係,就把要找的字描述出來也就可以了,例如要抓日期就做一個"(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)[0-9]{2}"的pattern就可以了。
而其實真正困難的地方在於很多pattern都要看到結果才會瞭解哪裡錯了。
看這個例子
字串 "ABCDC"
pattern "([A-Z]*).\1"
預期要抓到CDC的,結果卻是"A" "B" "CDC",因為*是0~n所以沒抓也算,而後面的\1如果前面group沒抓到,他也跟著什麼都沒有,最後只有"."抓到第一個結果的"A",同理抓到 第二個結果的"B",然後才抓到預期的"CDC",而改成"([A-Z]+).\1"就只會抓到"CDC"了。
最後誰能幫忙解釋一下"(?>X)",因為我實在分不出來他和(?:X)有什麼差別....
发表评论
-
Test
2006-05-06 12:29 703test -
JSP技巧篇---字符串日期格式转换
2006-05-18 22:07 7291有一些网友问我字符串转日期或日期转字符串要如何做,本 ... -
自定义集合中的排序
2006-05-19 11:33 7321、先自定义Comparator// 对象的比较器,如1 ... -
华为公司 java 面试题
2006-05-21 18:46 1098第一部分:选择题QUESTION NO: 11、 ... -
tomcat支持中文名的处理方式
2006-06-11 17:52 992在server.xml配置文件中,增加URIEncoding= ... -
進銷存系統有幾個資料庫?
2006-06-17 09:57 1066我在教授 軟體設計課程,尤其是以使用案例圖在說明架構設計時,每 ... -
Eclipse插件JSEclipse 1.5 发布
2006-06-18 12:35 977Eclipse插件JSEclipse 1.5 近日 ... -
如何在TOMCAT中调试JSP
2006-06-18 13:48 1223调试JSP时,在tomcat里改\conf\server.xm ... -
中文版API
2006-06-22 11:02 1057中文版API http://gceclub.s ... -
服务器在某些情况下需要进行的调整
2006-07-12 22:00 1559服务器在某些情况下需要进行的调整.============== ... -
采用输出内容
2006-07-16 22:45 867采用<JSP:FORWORD> 该方法是利用服务器 ... -
WebSphere中流行数据库连接池的配置(Oracle、SQL Server、Sybase、MySQL)
2006-07-24 16:15 6760本文介绍WebSphere下Oracle、SQL Serve ... -
MyEclipse+WebSphere 通过 JNDI 连接 Sybase 简介
2006-07-24 17:12 3581很久 ... -
Websphere Application Server心得
2006-07-28 10:27 1294Websphere Application Serve ... -
MyEclipse 5.0 M2 注册码及下载地址和Eclipse 3.2多国语言包
2006-07-30 12:13 2749MyEclipse 5.0 M2 注册码及下载地址 ... -
PrepareStatement中in中带问号的又一用法
2006-07-30 14:52 1192String strSQL = ... -
showModalDialog和showModelessDialog
2006-08-16 14:02 874一、showModalDialog和showModelessD ... -
Regular Expression in Java
2006-08-23 21:42 22161. Introduction 正規表示式(Regular E ... -
图解eclipse+myelcipse开发EJB
2006-08-29 14:08 956http://www2.blogjava.net/rickhu ... -
怎样给websphere管理页面设置权限?
2006-10-10 19:24 2101----步骤 1. 用计算机管理员账户进入本机wingdows ...
相关推荐
Mastering Regular Expressions(3rd) 英文无水印pdf 第3版 pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,...
正则表达式(Regular Expressions)是一种强有力的文本匹配工具,用于在字符串中执行模式匹配和提取信息。从给出的文件内容来看,我们正在讨论一本关于正则表达式的电子书——《Introducing Regular Expressions》,...
《Mastering Regular Expressions》(第三版)是正则表达式领域的权威著作,由拥有近30年开发经验的专家Jeffrey E.F. Friedl撰写。这本书深入浅出地介绍了正则表达式的概念、语法以及实际应用,是编程者提升正则...
而Delphi自XE2版本起,内置了RegularExpressions组件,它基于.NET Framework的System.Text.RegularExpressions类库,提供了一套原生的正则表达式支持。虽然它可能没有PerlRegEx那么灵活,但对于大部分日常的正则...
《Wrox - Beginning Regular Expressions》是一本专为初学者设计的正则表达式入门教程。这本书深入浅出地介绍了正则表达式的基本概念、语法和应用,旨在帮助读者掌握这一强大的文本处理工具。 正则表达式(Regular ...
#### 标题:Mastering Regular Expressions - **主要内容**:本书深入探讨了正则表达式的高级用法和技术细节,旨在帮助读者掌握正则表达式的各个方面。 #### 描述:Mastering Regular Expressions.pdf - **内容...
**"Regular Expressions Cookbook.pdf"** 这个标题明确指出本书的主题是正则表达式(Regular Expressions,简称 Regex)。正则表达式是一种强大的文本处理工具,被广泛应用于搜索、替换以及解析文本等任务中。...
PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正规表达式库.这些在执行正规表达式模式匹配时用与Perl 5同样的语法和语义是很有用的。Boost太庞大了,使用boost regex后,程序的编译速度...
Mastering Python Regular Expressions 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请...
正则表达式(Regular Expressions)是一种强大的文本处理工具,用于在字符串中执行搜索、替换、提取等操作,它是一种在计算机科学和编程领域广泛使用的工具。正则表达式被设计为一种模式,能够匹配一系列符合特定...
To introduce readers to regular expressions in several technologies. While the material is primarily for people who have little or no experience with regular expressions, there is also some content ...
PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl 兼容的正则表达式库。这些在执行正规表达式模式匹配时用与Perl 5同样的语法和语义是很有用的。
书名:Mastering Regular Expressions, 3rd Edition 格式:CHM 语言:English 简介: Regular expressions are an extremely powerful tool for manipulating text and data. They are now standard ...
本部分内容主要介绍了正则表达式的相关知识,包括锚点、字符集、特殊字符、字符类、量词、模式修饰符、逃脱字符、正则表达式元字符、前后匹配、位置匹配等。 1. 锚点:锚点是正则表达式中的特殊字符,用于指定匹配...