經常使用正則表達式(?i)忽略字母的大小寫!

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位或前面有區號例如(02287341628
  
* 12^[a-z A-0-9 _]+@[a-z A-0-9 _]+(/.[a-z A-0-9 _]+)+(/,[a-z A-0-9 _]+@[a-z A-0-9 _]+(/.[a-z A-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$&] 就能夠了。

說了那麼多,不知道是否明白了? 
java

相關文章
相關標籤/搜索