Java Regular Expressions Syntax

Java Regular Expressions Syntax

關鍵字: java regex syntax

一、正則表達式語法

1.1.字符

x    字符 x。例如a表示字符a

//    反斜線字符。在書寫時要寫爲////。(注意:因爲java在第一次解析時把////解析成正則表達式//,在第二次解析時再解析爲/,所以凡是不是1.1列舉到的轉義字符,包括1.1的//,而又帶有/的都要寫兩次)

/0n    帶有八進制值 0的字符 n (0 <= n <= 7)

/0nn    帶有八進制值 0的字符 nn (0 <= n <= 7)

/0mnn    帶有八進制值 0的字符 mnn(0 <= m <= 3、0 <= n <= 7)

/xhh    帶有十六進制值 0x的字符 hh

/uhhhh    帶有十六進制值 0x的字符 hhhh

/t    製表符 ('/u0009')

/n    新行(換行)符 ('/u000A')

/r    回車符 ('/u000D')

/f    換頁符 ('/u000C')

/a    報警 (bell) 符 ('/u0007')

/e    轉義符 ('/u001B')

/cx    對應於 x 的控制符

1.2.字符類

[abc]    a、b或 c(簡單類)。例如[egd]表示包含有字符e、g或d。

[^abc]    任何字符,除了 a、b或 c(否定)。例如[^egd]表示不包含字符e、g或d。

[a-zA-Z]    a到 z或 A到 Z,兩頭的字母包括在內(範圍)

[a-d[m-p]]    a到 d或 m到 p:[a-dm-p](並集)

[a-z&&[def]]    d、e或 f(交集)

[a-z&&[^bc]]    a到 z,除了 b和 c:[ad-z](減去)

[a-z&&[^m-p]]    a到 z,而非 m到 p:[a-lq-z](減去)

1.3.預定義字符類(注意反斜槓要寫兩次,例如/d寫爲//d)

.    任何字符(與行結束符可能匹配也可能不匹配)

/d    數字:[0-9]

/D    非數字: [^0-9]

/s    空白字符:[ /t/n/x0B/f/r]

/S    非空白字符:[^/s]

/w    單詞字符:[a-zA-Z_0-9]

/W    非單詞字符:[^/w]

1.4.POSIX 字符類(僅 US-ASCII)(注意反斜槓要寫兩次,例如/p{Lower}寫爲//p{Lower})

/p{Lower}    小寫字母字符:[a-z]。

/p{Upper}    大寫字母字符:[A-Z]

/p{ASCII}    所有 ASCII:[/x00-/x7F]

/p{Alpha}    字母字符:[/p{Lower}/p{Upper}]

/p{Digit}    十進制數字:[0-9]

/p{Alnum}    字母數字字符:[/p{Alpha}/p{Digit}]

/p{Punct}    標點符號:!"#$%&'()*+,-./:;<=>?@[/]^_`{|}~

/p{Graph}    可見字符:[/p{Alnum}/p{Punct}]

/p{Print}    可打印字符:[/p{Graph}/x20]

/p{Blank}    空格或製表符:[ /t]

/p{Cntrl}    控制字符:[/x00-/x1F/x7F]

/p{XDigit}    十六進制數字:[0-9a-fA-F]

/p{Space}    空白字符:[ /t/n/x0B/f/r]

1.5.java.lang.Character 類(簡單的 java 字符類型)

/p{javaLowerCase}    等效於 java.lang.Character.isLowerCase()

/p{javaUpperCase}    等效於 java.lang.Character.isUpperCase()

/p{javaWhitespace}    等效於 java.lang.Character.isWhitespace()

/p{javaMirrored}    等效於 java.lang.Character.isMirrored()

1.6.Unicode 塊和類別的類

/p{InGreek}    Greek 塊(簡單塊)中的字符

/p{Lu}    大寫字母(簡單類別)

/p{Sc}    貨幣符號

/P{InGreek}    所有字符,Greek 塊中的除外(否定)

[/p{L}&&[^/p{Lu}]]     所有字母,大寫字母除外(減去)

1.7.邊界匹配器

^    行的開頭,請在正則表達式的開始處使用^。例如:^(abc)表示以abc開頭的字符串。注意編譯的時候要設置參數MULTILINE,如 Pattern p = Pattern.compile(regex,Pattern.MULTILINE);

$    行的結尾,請在正則表達式的結束處使用。例如:(^bca).*(abc$)表示以bca開頭以abc結尾的行。

/b    單詞邊界。例如/b(abc)表示單詞的開始或結束包含有abc,(abcjj、jjabc 都可以匹配)

/B    非單詞邊界。例如/B(abc)表示單詞的中間包含有abc,(jjabcjj匹配而jjabc、abcjj不匹配)

/A    輸入的開頭

/G    上一個匹配的結尾(個人感覺這個參數沒什麼用)。例如//Gdog表示在上一個匹配結尾處查找dog如果沒有的話則從開頭查找,注意如果開頭不是dog則不能匹配。

/Z    輸入的結尾,僅用於最後的結束符(如果有的話)

行結束符 是一個或兩個字符的序列,標記輸入字符序列的行結尾。

以下代碼被識別爲行結束符:

‐新行(換行)符 ('/n')、

‐後面緊跟新行符的回車符 ("/r/n")、

‐單獨的回車符 ('/r')、

‐下一行字符 ('/u0085')、

‐行分隔符 ('/u2028') 或

‐段落分隔符 ('/u2029)。

/z    輸入的結尾

當編譯模式時,可以設置一個或多個標誌,例如

Pattern pattern = Pattern.compile(patternString,Pattern.CASE_INSENSITIVE + Pattern.UNICODE_CASE);

下面六個標誌都是支持的:

‐CASE_INSENSITIVE:匹配字符時與大小寫無關,該標誌默認只考慮US ASCII字符。

‐UNICODE_CASE:當與CASE_INSENSITIVE結合時,使用Unicode字母匹配

‐MULTILINE:^和$匹配一行的開始和結尾,而不是整個輸入

‐UNIX_LINES: 當在多行模式下匹配^和$時,只將'/n'看作行終止符

‐DOTALL: 當使用此標誌時,.符號匹配包括行終止符在內的所有字符

‐CANON_EQ: 考慮Unicode字符的規範等價

1.8.Greedy 數量詞

X?    X,一次或一次也沒有

X*    X,零次或多次

X+    X,一次或多次

X{n}    X,恰好 n 次

X{n,}    X,至少 n 次

X{n,m}    X,至少 n 次,但是不超過 m 次

1.9.Reluctant 數量詞

X??    X,一次或一次也沒有

X*?    X,零次或多次

X+?    X,一次或多次

X{n}?    X,恰好 n 次

X{n,}?    X,至少 n 次

X{n,m}?    X,至少 n 次,但是不超過 m 次

1.10.Possessive 數量詞

X?+    X,一次或一次也沒有

X*+    X,零次或多次

X++    X,一次或多次

X{n}+    X,恰好 n 次

X{n,}+    X,至少 n 次

X{n,m}+    X,至少 n 次,但是不超過 m 次

Greedy,Reluctant,Possessive的區別在於:(注意僅限於進行.等模糊處理時)

greedy量 詞被看作“貪婪的”,因爲它第一次就讀入整個被模糊匹配的字符串。如果第一個匹配嘗試(整個輸入字符串)失敗,匹配器就會在被匹配字符串中的最後一位後退 一個字符並且再次嘗試,重複這個過程,直到找到匹配或者沒有更多剩下的字符可以後退爲止。根據表達式中使用的量詞,它最後試圖匹配的內容是1 個或者0個字符。

但是,reluctant量詞采取相反的方式:它們從被匹配字符串的開頭開始,然後逐步地一次讀取一個字符搜索匹配。它們最後試圖匹配的內容是整個輸入字符串。

最後,possessive量詞總是讀完整個輸入字符串,嘗試一次(而且只有一次)匹配。和greedy量詞不同,possessive從不後退。


1.11.Logical 運算符

XY    X 後跟 Y

X|Y    X 或 Y

(X)    X,作爲捕獲組。例如(abc)表示把abc作爲一個整體進行捕獲

1.12.Back 引用

/n    任何匹配的 nth捕獲組

捕獲組可以通過從左到右計算其開括號來編號。例如,在表達式 ((A)(B(C)))中,存在四個這樣的組:

1        ((A)(B(C)))

2        /A

3        (B(C))

4        (C)

在表達式中可以通過/n來對相應的組進行引用,例如(ab)34/1就表示ab34ab,(ab)34(cd)/1/2就表示ab34cdabcd。

1.13.引用

/    Nothing,但是引用以下字符

/Q    Nothing,但是引用所有字符,直到 /E。QE之間的字符串會原封不動的使用(1.1中轉義字符的除外)。例如, ab//Q{|}////E

可以匹配ab{|}//

/E    Nothing,但是結束從 /Q開始的引用

1.14.特殊構造(非捕獲)

(?:X)    X,作爲非捕獲組

(?idmsux-idmsux)     Nothing,但是將匹配標誌由 on 轉爲 off。比如:表達式 (?i)abc(?-i)def 這時,(?i) 打開不區分大小寫開關,abc 匹配

idmsux說明如下:

‐i CASE_INSENSITIVE :US-ASCII 字符集不區分大小寫。(?i)

‐d UNIX_LINES : 打開UNIX換行符

‐m MULTILINE :多行模式(?m)

UNIX下換行爲/n

WINDOWS下換行爲/r/n(?s)

‐u UNICODE_CASE : Unicode 不區分大小寫。(?u)

‐x COMMENTS :可以在pattern裏面使用註解,忽略pattern裏面的whitespace,以及"#"一直到結尾(#後面爲註解)。(?x)例如(?x)abc#asfsdadsa可以匹配字符串abc

(?idmsux-idmsux:X)     X,作爲帶有給定標誌 on - off 的非捕獲組。與上面的類似,上面的表達式,可以改寫成爲:(?i:abc)def,或者 (?i)abc(?-i:def)

(?=X)    X,通過零寬度的正 lookahead。零寬度正先行斷言,僅當子表達式 X 在 此位置的右側匹配時才繼續匹配。例如,/w+(?=/d) 表示字母后面跟數字,但不捕獲數字(不回溯)

(?!X)    X,通過零寬度的負 lookahead。零寬度負先行斷言。僅當子表達式 X 不在 此位置的右側匹配時才繼續匹配。例如,/w+(?!/d) 表示字母后面不跟數字,且不捕獲數字。

(?<=X)    X,通過零寬度的正 lookbehind。零寬度正後發斷言。僅當子表達式 X 在 此位置的左側匹配時才繼續匹配。例如,(?<=19)99 表示99前面是數字19,但不捕獲前面的19。(不回溯)

(?<!X)    X,通過零寬度的負 lookbehind。零寬度負後發斷言。僅當子表達式 X 不在此位置的左側匹配時才繼續匹配。例如,(?<!19)99 表示99前面不能是19,且不捕獲前面的東東。

(?>X)    X,作爲獨立的非捕獲組(不回溯)

(?:X)與(?>X)的區別在於(?>X)是不回溯的。例如被匹配的字符串爲abcm,當表達式爲a(?:b|bc)m是可以匹配 的,而當表達式是a(?>b|bc)m時是不能匹配的,因爲當後者匹配到b時,由於已經匹配,就跳出了非捕獲組,而不再次對組內的字符進行匹配。可 以加快速度。
下面這段代碼,只輸出abm而不會輸出abcm。當表達式爲a(?:b|bc)m時可以輸出abcm。
Java代碼
  1. Pattern pattern = Pattern.compile("a(?>b|bc)m" );  
  2.           
  3. Matcher m = pattern.matcher("abcmkfabm" );  
  4. while (m.find()){  
  5.     System.out.println(m.group());  
  6. }  
Pattern pattern = Pattern.compile("a(?>b|bc)m");
		
Matcher m = pattern.matcher("abcmkfabm");
while(m.find()){
	System.out.println(m.group());
}

說明:回溯算法的基本思想是:從一條路往前走,能進則進,不能進則退回來,換一條路再試。
二、例子
1.
Java代碼
  1. /**  
  2.  * 以非字母和數字作爲分隔符,輸出數據  
  3.  * @param input  
  4.  */   
  5. public  static  void  testSplit(String input){  
  6.     ///p{name}: 一個指定的字符類   
  7.     //Punct :非字母或數字ASCII [/p{Print}&&/P{Alnum}]    
  8.     Pattern pattern = Pattern.compile("//s*//p{Punct}//s*" );  
  9.     if (input ==null  || input =="" ){  
  10.         input = "begin | test { split 123456 }00end" ;  
  11.     }  
  12.     String[] tokens = pattern.split(input);  
  13.     for (String str:tokens){  
  14.         System.out.println(str);  
  15.     }  
  16. }  
/**
 * 以非字母和數字作爲分隔符,輸出數據
 * @param input
 */
public static void testSplit(String input){
	///p{name}: 一個指定的字符類
	//Punct :非字母或數字ASCII [/p{Print}&&/P{Alnum}] 
	Pattern pattern = Pattern.compile("//s*//p{Punct}//s*");
	if(input ==null || input ==""){
		input = "begin | test { split 123456 }00end";
	}
	String[] tokens = pattern.split(input);
	for(String str:tokens){
		System.out.println(str);
	}
}

2.
Java代碼
  1. /**  
  2.  * in:給定模式((1?[0-9]):([0-5][0-9]))[ap]m,並且輸入11:59am out:Match ((11):(59))am  
  3.  */   
  4. public  static  void  testGroupMatch() {  
  5.     Scanner in = new  Scanner(System.in);  
  6.     System.out.println("Enter pattern: " );  
  7.     String patternString = in.nextLine();  
  8.   
  9.     Pattern pattern = null ;  
  10.     try  {  
  11.         pattern = Pattern.compile(patternString);  
  12.     } catch  (PatternSyntaxException e) {  
  13.         System.out.println("Pattern syntax error" );  
  14.         System.exit(1 );  
  15.     }  
  16.   
  17.     while  (true ) {  
  18.         System.out.println("Enter string to match: " );  
  19.         String input = in.nextLine();  
  20.         if  (input == null  || input.equals("" ))  
  21.             return ;  
  22.         Matcher matcher = pattern.matcher(input);  
  23.         if  (matcher.matches()) {  
  24.             System.out.println("Match!" );  
  25.         int  g = matcher.groupCount();// 獲得總的分組數   
  26.             if  (g > 0 ) {  
  27.                 for  (int  i = 0 ; i < input.length(); i++) {  
  28.                     for  (int  j = 1 ; j <= g; j++) {// 第0個分組代表所有的分組,第一個實際分組的索引是1。   
  29.                         if  (i == matcher.start(j)) {// 此位置是分組的起始   
  30.                             System.out.print('(' );  
  31.                         }  
  32.                     }  
  33.                         System.out.print(input.charAt(i));  
  34.                     for  (int  j = 1 ; j <= g; j++) {  
  35.                             if  (i + 1  == matcher.end(j)) {// 下一個位置是分組的結束   
  36.                                 System.out.print(')' );  
  37.                         }  
  38.                     }  
  39.                 }  
  40.                 System.out.println();  
  41.             }  
  42.         } else   
  43.             System.out.println("No match" );  
  44.     }  
  45.  
/**
 * in:給定模式((1?[0-9]):([0-5][0-9]))[ap]m,並且輸入11:59am out:Match ((11):(59))am
 */
public static void testGroupMatch() {
	Scanner in = new Scanner(System.in);
	System.out.println("Enter pattern: ");
	String patternString = in.nextLine();

	Pattern pattern = null;
	try {
		pattern = Pattern.compile(patternString);
	} catch (PatternSyntaxException e) {
		System.out.println("Pattern syntax error");
		System.exit(1);
	}

	while (true) {
		System.out.println("Enter string to match: ");
		String input = in.nextLine();
		if (input == null || input.equals(""))
			return;
		Matcher matcher = pattern.matcher(input);
		if (matcher.matches()) {
			System.out.println("Match!");
		int g = matcher.groupCount();// 獲得總的分組數
			if (g > 0) {
				for (int i = 0; i < input.length(); i++) {
					for (int j = 1; j <= g; j++) {// 第0個分組代表所有的分組,第一個實際分組的索引是1。
						if (i == matcher.start(j)) {// 此位置是分組的起始
							System.out.print('(');
						}
					}
						System.out.print(input.charAt(i));
					for (int j = 1; j <= g; j++) {
							if (i + 1 == matcher.end(j)) {// 下一個位置是分組的結束
								System.out.print(')');
						}
					}
				}
				System.out.println();
			}
		} else
			System.out.println("No match");
	}
}

3.
Java代碼
  1. /**  
  2.  * This program displays all URLs in a web page by matching  
  3.  * a regular expression that describes the <a href=...> HTML tag.   
  4.  * @param urlString  
  5.  */   
  6. public  static  void  testHrefMatch(String urlString) {  
  7.     if  (urlString == null  || urlString == "" ) {  
  8.         urlString = "http://java.sun.com" ;  
  9.     }  
  10.     try  {  
  11.         InputStreamReader in = new  InputStreamReader(new  URL(urlString)  
  12.                 .openStream());  
  13.         StringBuilder input = new  StringBuilder();  
  14.         int  ch;  
  15.         while  ((ch = in.read()) != -1 ) {  
  16.             input.append((char ) ch);  
  17.         }  
  18.         String patternString = "<a//s+href//s*=//s*(/"[^/"]*/"|[^//s>])//s*>" ;  
  19.         Pattern pattern = Pattern.compile(patternString,  
  20.                 Pattern.CASE_INSENSITIVE);  
  21.         Matcher matcher = pattern.matcher(input);  
  22.         while  (matcher.find()) {  
  23.             int  start = matcher.start();  
  24.             int  end = matcher.end();  
  25.             String match = input.substring(start, end);  
  26.             System.out.println(match);  
  27.         }  
  28.   
  29.     } catch  (Exception e) {  
  30.         e.printStackTrace();  
  31.     }  
  32. }  
	/**
	 * This program displays all URLs in a web page by matching
	 * a regular expression that describes the <a href=...> HTML tag. 
	 * @param urlString
	 */
	public static void testHrefMatch(String urlString) {
		if (urlString == null || urlString == "") {
			urlString = "http://java.sun.com";
		}
		try {
			InputStreamReader in = new InputStreamReader(new URL(urlString)
					.openStream());
			StringBuilder input = new StringBuilder();
			int ch;
			while ((ch = in.read()) != -1) {
				input.append((char) ch);
			}
			String patternString = "<a//s+href//s*=//s*(/"[^/"]*/"|[^//s>])//s*>";
			Pattern pattern = Pattern.compile(patternString,
					Pattern.CASE_INSENSITIVE);
			Matcher matcher = pattern.matcher(input);
			while (matcher.find()) {
				int start = matcher.start();
				int end = matcher.end();
				String match = input.substring(start, end);
				System.out.println(match);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
發佈了33 篇原創文章 · 獲贊 4 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章