1。^/d+$ //匹配非負整數(正整數 + 0)
2。^[0-9]*[1-9][0-9]*$ //匹配正整數
3。^((-/d+)|(0+))$ //匹配非正整數(負整數 + 0)
4。^-[0-9]*[1-9][0-9]*$ //匹配負整數
5。^-?/d+$ //匹配整數
6。^/d+(/./d+)?$ //匹配非負浮點數(正浮點數 + 0)
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+)?))$ //匹配非正浮點數(負浮點數 + 0)
9。^(-(([0-9]+/.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*/.[0-9]+)|([0-9]*[1-9][0-9]*)))$ //匹配負浮點數
10。^(-?/d+)(/./d+)?$ //匹配浮點數
11。^[A-Za-z]+$ //匹配由26個英文字母組成的字符串
12。^[A-Z]+$ //匹配由26個英文字母的大寫組成的字符串
13。^[a-z]+$ //匹配由26個英文字母的小寫組成的字符串
14。^[A-Za-z0-9]+$ //匹配由數字和26個英文字母組成的字符串
15。^/w+$ //匹配由數字、26個英文字母或者下划線組成的字符串
16。^[/w-]+(/.[/w-]+)*@[/w-]+(/.[/w-]+)+$ //匹配email地址
17。^[a-zA-z]+://匹配(/w+(-/w+)*)(/.(/w+(-/w+)*))*(/?/S*)?$ //匹配url
18。匹配中文字符的正則表達式: [/u4e00-/u9fa5]
19。匹配雙字節字符(包括漢字在內):[^/x00-/xff]
20。應用:計算字符串的長度(一個雙字節字符長度計2,ASCII字符計1)
String.prototype.len=function(){return this.replace([^/x00-/xff]/g,"aa").length;}
21。匹配空行的正則表達式:/n[/s| ]*/r
22。匹配HTML標記的正則表達式:/<(.*)>.*<///1>|<(.*) //>/
23。匹配首尾空格的正則表達式:(^/s*)|(/s*$)
* 正則表達式用例
* 1、^/S+[a-z A-Z]$ 不能為空 不能有空格 只能是英文字母
* 2、/S{6,} 不能為空 六位以上
* 3、^/d+$ 不能有空格 不能非數字
* 4、(.*)(/.jpg|/.bmp)$ 只能是jpg和bmp格式
* 5、^/d{4}/-/d{1,2}-/d{1,2}$ 只能是2004-10-22格式
* 6、^0$ 至少選一項
* 7、^0{2,}$ 至少選兩項
* 8、^[/s|/S]{20,}$ 不能為空 二十字以上
* 9、^/+?[a-z0-9](([-+.]|[_]+)?[a-z0-9]+)*@([a-z0-9]+(/.|/-))+[a-z]{2,6}$郵件
* 10、/w+([-+.]/w+)*@/w+([-.]/w+)*/./w+([-.]/w+)*([,;]/s*/w+([-+.]/w+)*@/w+([-.]/w+)*/./w+([-.]/w+)*)* 輸入多個地址用逗號或空格分隔郵件
* 11、^(/([0-9]+/))?[0-9]{7,8}$電話號碼7位或8位或前面有區號例如(022)87341628
* 12、^[a-z A-Z 0-9 _]+@[a-z A-Z 0-9 _]+(/.[a-z A-Z 0-9 _]+)+(/,[a-z A-Z 0-9 _]+@[a-z A-Z 0-9 _]+(/.[a-z A-Z 0-9 _]+)+)*$
* 只能是字母、數字、下划線;必須有@和.同時格式要規范 郵件
* 13 ^/w+@/w+(/./w+)+(/,/w+@/w+(/./w+)+)*$上面表達式也可以寫成這樣子,更精練。
14 ^/w+((-/w+)|(/./w+))*/@/w+((/.|-)/w+)*/./w+$
// 限定條件
final String CONDITION = "(?=.*[a-z])(?=.*[A-Z])(?=.*//d)";
// 允許出現的字符
final String SPECIAL_CHAR = "[-A-Za-z0-9!$%&()/;<?{}//[//]^////]";
// 數量
final String QUANTITY = "{8,16}";
1 樓的回復
(?=.*[a-z]) 表示當前位置后面必須出現 .*[a-z] 的字符,這個可以理解為必須出現小寫字母。
或者可以理解為某一個字符間的縫隙必須滿足的條件,這個僅僅作為條件判斷並不能匹配任何字
符,因為這屬於非捕獲組中的環視(lookarround)零寬度匹配。
舉個大家常見的例子:
表達式:Win(?=XP)
現有字符串 WinXP 和 WinNT,在應用這個表達式時前者能與之進行匹配,為什么呢?
當匹配器指示到 (?=XP) 時,也就是在 n 字母后面的縫隙,這個縫隙必須滿足的
條件是:后面的字符必須是 XP,如果是的話,匹配成功,否則匹配失敗。由於
(?=XP) 是匹配縫隙的,因此並不會把 XP 給匹配輸出,而只輸出了 Win 因此,這
個表達式的語義可以看作是:找到后面為“XP”字符所有的 Win。
假如,我們把表達式寫成 Win(?=XP)(?=NT) 這樣的話,那么這個語義是:找出后面
為“XP”並且為“NT”字符所有的 Win 可以想象,這是個
永遠無法滿足的匹配。(?=XP)(?=NT) 這個表示當前的縫隙必須同時滿足的條件。
把這個表達式再改一下,改成 Win(?=.*XP)(?=.*NT) 這個表示 Win 的后面必須出現
XP 與 NT,位置和順序都是無關的(這主要是 .* 的作用)。當然了這個表達式的效
率是比較低的,得向后進行兩次斷言。
如果字符串是 WincbaXPabcNT 這個字符串,當匹配指示器走到 n 后面的縫隙時開始
進行向后斷言,首先對 .*XP 進行斷言,很明顯能將 cbaXP 匹配成功,這時第一個斷
言完成,再對 .*NT 斷言,可以看出 cbaXPabcNT 能與其匹配成功,這時第二個斷言完
成,因此表達式 Win(?=.*XP)(?=.*NT) 能對 WincbaXPabcNT 進行匹配。
同理 WincbaNTabcXP 也是同樣的效果。
如果能理解上面的這些,對於 (?=.*[a-z])(?=.*[A-Z])(?=.*//d) 這個的理應該不會
很難吧,這個只不過是必須同時滿足三個條件。
這個表達式在開始部分就進行斷言,即索引為 0 的地方,也就是第一個字符的前面的
縫隙,這個縫隙后面的字符必須滿足 .*[a-z] .*[A-Z] .*//d 三個條件,也就是說
必后面必須出現至少一個小寫字母、至少一個大寫母、至少一個數字。
至於表達式 2 的使用,也就是 [ ] 內字符的轉義需要注意一下。
^ 和 - 在 [ ] 結構的表達式中是有一定意義的。
[^abc] 表示除 abc 以外所有的字符,注意,這是放在最前面表示這個意思,
如果改成 [a^bc] 這個僅表示 a ^ b c 四個字符。如果需要匹配 ^ 這個字符
的話,千萬不要把它放在第一個,如果一定要放在第一個的話,得使用轉義符。
- 在 [ ] 表示字符的范圍,比如 [a-z] 表示 a 與 z 之間的 26 個字母,
[a-zA-Z] 這個表示 a-z 和 A-Z 的 52 個字母。使用范圍得注意了,如果寫成
[z-a] 的話,在 Pattern.compile 編譯表達式時會對范圍進行檢查,這時會產
生異常,因此在使用 - 范圍時,后面的 Unicode 值必須大於等於前面的 Unicode
值。
如果要匹配“-”的話,盡量不要把 - 這個放在字符之間,可以放在 [ ] 的兩邊。
比如 [-a-z] 這就能匹配 26 個小寫字母和“-”了。當然了,我們也可以寫成
[a-z-A-Z] 這個可以匹配 52 字母和“-”,但是這樣很不直觀,我們寧願寫成
[a-zA-Z-] 或者 [-a-zA-Z] 這樣。
2:不以某某開頭 ,比如不以www開頭
Java code
public class Test {
public static void main(String[] args) {
String[] strs = { "abc1232", "wwwadsf", "awwwfas", "wwadfsf", "", "ww", " ", "www" };
String regex = "(?:(?!^www).)*";
for(String str : strs) {
System.out.printf("%-7s %s%n", str, str.matches(regex));
}
}
}
(?!X) 專業名稱為 Negative Lookahead,表示字符間縫隙后面不允許出現的字符,
即匹配字符間的縫隙,如果縫隙后的字符不是 X 的話,那這個縫隙就匹配成功。
舉個例子,aab 和 aac,現有表達式 aa(?!b) 這時我們能匹配到的字符串是 aac,
因為 aa 的后面的縫隙之后不允許出現字符 b,因此只有 aac 進行了匹配。
再來看個示例:
Java code
public class Test {
public static void main(String[] args) {
String str = "AQuickBrownFoxJumpsOverTheLazyDog";
String[] strs = str.split("(?<!^)(?=[A-Z])");
for(String s : strs) {
System.out.println(s);
}
}
}
根據大寫字母拆分字符串。當然了,這個使用字符串進行分析同樣也能進行拆分,
但是使用正則表達式來拆的話更為便捷直觀一些。
在進行這種拆分時,由於在拆分后的字符數不能減少,因此只能使用零寬度的
lookaround 功能進行匹配,lookaround 包括四個,即:
Java code
(?=X) (?!X) (?<=X) (?<!X)
來看一下這個表達式:(? <!^)(?=[A-Z])
前面說到過 (?!) 表示縫隙后面不允許出現的東西,而 (? <!) 表示縫隙前不允許出現的東西。
(?=) 表示縫隙后允許出現的東西,(? <=) 表示縫隙前允許出現的東西。
這個表達式在拆分時,根據零寬度匹配縫隙進行拆分的,這個縫隙必須滿足以下條件:
(? <!^) 表示縫隙不允許前不能是行開始,即縫隙不能出現在首字母的前面。
(?=[A-Z]) 表示縫隙后面允許出現 A-Z 的大寫字母。
這時這個表達式就匹配了下面帶有 | 的縫隙:
Java code
A|Quick|Brown|Fox|Jumps|Over|The|Lazy|DogPS:不加 (?<!^) 的話,會變成:|A|Quick|Brown|Fox|Jumps|Over|The|Lazy|Dog
根據 split 的功能,正則表達式處理程序就根據上面的 | 將字符串給拆分開來了。
3,不區分大小寫
不加任何限制的匹配是匹配分大小寫的,但是正則表達式中可以進行改變,
有兩種方式:參數式和內嵌式。
來看個示例:
Java code
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
String str = "Book";
Pattern pattern = Pattern.compile("book");
Matcher matcher = pattern.matcher(str);
System.out.println(matcher.matches());
}
}
上面的這個表達式 book 是不能匹配字符串 Book 的,這時我們只要給定編譯時的參數就可以了:
Pattern pattern = Pattern.compile("book", Pattern.CASE_INSENSITIVE);
Pattern.CASE_INSENSITIVE 這是一個 int 類型的常量,值為 2。表示表達式忽略大小寫進行區配。
如果我們不采用 Pattern 和 Matcher 兩個類來匹配的話,只是使用 String 的 matches 方法的話,
我們就不能指定表達式的編譯參數了,這時就需要采用內嵌標志表達式了,與 Pattern.CASE_INSENSITIVE
對應的內嵌標志表達式是 (?i),它有四種形式:
1,(?i)
2,(?-i)
3,(?i:X)
4,(?-i:X)
不帶有 - 的是開標志,帶有 - 的是關標志。
把上面的代碼改成這樣:
Java code
public class Test {
public static void main(String[] args) {
String str = "Book";
String regex = "(?i)book";
System.out.println(str.matches(regex));
}
}
我們就達到了同樣的效果,當然這樣並不是最好的,因為字符串中只有 B 是大寫的,
我們沒有必要把所有的字符都進行不區分大小寫匹配,我們可以在打開標志,用 (?i) 的
第二種形式馬上關掉它:
String regex = "(?i)b(?-i)ook";
這樣的話,只有 b 是區分大小寫了,而 (?-i) 后面的還是得區分大小寫匹配的。這樣寫
可能看上去很不順眼,我們還能使用第 3 種形式直接指定某些字符是不區分大小寫的。
String regex = "(?i:b)ook";
這樣的表達式與上面的那個在語義上是相同的。就效率上肯定是優於一下子開,一下子關的。
可見內嵌標志表達式要比指定編譯參數的功能強大許多。
使用建議:如果能確定某些字符的大小寫時,盡量使用已確定的字符,對於不確定的可以采用
(?i:X) 的方式指定。因此打開不區分大小寫開關時,對匹配的性能是有一定影響的。
思考一下:String regex = "(?i)b(?-i:oo)k"; 這個表達式的意思?
另外:第 1 和第 4,我沒看明白需要了解什么,請在下面的樓層中具體地說明一下。
1:多行匹配
在默認的情況下 . 是不能匹配行結束符的(行結束符有 6 個,具體的可以看看 Pattern 的 API DOC)
同樣,可以像不匹配大小寫匹配那樣使用編譯參數:Pattern.DOTALL
如果還得區分大小寫的話,還得加上上面說到的 Pattern.CASE_INSENSITIVE 這個,舉個例子:
Java code
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
String str = "<table> /n" + " <tr> /n" + " <td> /n" + " Hello World! /n" + " </td> /n" + " </tr> /n" + "</table>";
String regex = "<td>(.+?)</td>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()) {
System.out.println(matcher.group(1).trim());
}
}
}
上面這個是不能從 str 抽取出東西的,因為 td 的后面帶有換行符,我們只要更改一下:
Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
這樣就行了,如果 td 還得不區分大小寫的話,再改成:
Java code
Pattern pattern = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
這樣的話,td 哪怕是大寫的這個表達式都能把 td 之間的字符區抽取出來。
當然和 Pattern.CASE_INSENSITIVE 一樣,Pattern.DOTALL 也有內嵌標志表達式,即 (?s)
s 的意思表示 single-line 就是忽略換行符什么的,只看成單行進行處理。
這個表達式使用內嵌 (?s) 的話可以改為:
Java code
String regex = "(?s)<td>(.+?)</td>";如果還要不區分大小寫的話,再加上 i 標志:String regex = "(?s)(?i)<td>(.+?)</td>";但這樣顯得很拖沓,可以把它們合並起來:String regex = "(?is)<td>(.+?)</td>"; // 秩序無所謂
最后需要說明一下的是,我曾看到過由於不明白 DOTALL,為了讓 . 匹配行結束符,直接把表達式寫成:
Java code
String regex = "<td>((.|//s)+?)</td>";
這樣做是極其危險的,由於選擇結構的匹配效率問題,這樣做在比較長的字符串時會造成堆棧溢出,
使程序崩潰,如果使用 DOTALL 或者 (?s) 的話就不會出現這種情況。
4:2個單元的或操作
| 稱為多選結構,用於匹配 | 之中的任何一個,拿你的例子來說明:
Java code
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
String str = "<img src=/"http://www.google.com/1.gif/"/>/n" + "<img src=/"http://3w.google.com/1.gif/"/>/n" + "<img src=/"http://abc.baidu.com/1.gif/"/>";
String regex = "<img//ssrc=/"http://(?:ww|3)w.google.com/1.gif/"/>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
注意到其中的 (?:ww|3) 在進行多選匹配時盡量找出多選中的規律,以減少多選的字符,
www 和 3w 在最后一個字符可以共用,前面的不一樣。
(?: ) 的意思表示組成一組,如果沒有 (?: ) 這樣的話,表達式就變成了:
Java code
String regex = "<img//ssrc=/"http://ww|3w.google.com/1.gif/"/>";
這樣的語義完全變掉了,| 是在一組中進行選擇,由於上面的那個表達式中沒有組,就把整個表
達式作為了一組,使用 | 的話,就進行了整個表達式的多選結構了。這個表達式的意思是:
匹配 <img ssrc="http://ww 或者是 3w.google.com/1.gif"/>,這樣的結果並不是我們所要的。
我們僅僅需要在 ww 和 3 之間進行選擇,這時只要把 ww 和 3 放在一組中進行多選擇就可以了,
變成 (?:ww|3)。
還有,在多選結構中盡量把出現頻率高的放在前面,這樣可以加快匹配速度。
多選結構的效率在傳統型的引擎中是效率低下的,如果是單個字符的選擇,比如 a $ & 之中的一個,
那就不要使用 (?:a|$|&) 了,可以直接使用字符類 [a$&] 就可以了。
說了那么多,不知道是否明白了?