天天看點

Java入門 - 語言基礎 - 18.正規表達式正規表達式

原文位址: http://www.work100.net/training/java-regular-expression.html 更多教程: 光束雲 - 免費課程

本章節内容在 阿裡 編輯器顯示異常,請進入原文檢視

正規表達式

請參照如上

章節導航

進行閱讀

1.概述

正規表達式定義了字元串的模式。

正規表達式可以用來搜尋、編輯或處理文本。

正規表達式并不僅限于某一種語言,但是在每種語言中有細微的差别。

正規表達式執行個體

一個字元串其實就是一個簡單的正規表達式,例如

Hello World

正規表達式比對 "

Hello World

" 字元串。

.

(點号)也是一個正規表達式,它比對任何一個字元如:"

a

" 或 "

1

"。

下表列出了一些正規表達式的執行個體及描述:

描述

this is text

比對字元串 "

this is text

"

this\s+is\s+text

注意字元串中的

\s+

比對單詞 "

this

" 後面的

\s+

可以比對多個空格,之後比對

is

字元串,再之後

\s+

比對多個空格然後再跟上

text

字元串。

可以比對這個執行個體:

this is text

^\d+(\.\d+)?

^

定義了以什麼開始

\d+

比對一個或多個數字

?

設定括号内的選項是可選的

\.

比對 "

.

"

可以比對的執行個體:"

5

", "

1.5

" 和 "

2.21

Java 正規表達式和 Perl 的是最為相似的。

java.util.regex

包主要包括以下三個類:

  • Pattern

    類:

pattern

對象是一個正規表達式的編譯表示。

Pattern

類沒有公共構造方法。要建立一個

Pattern

對象,你必須首先調用其公共靜态編譯方法,它傳回一個

Pattern

對象。該方法接受一個正規表達式作為它的第一個參數。

  • Matcher

Matcher

對象是對輸入字元串進行解釋和比對操作的引擎。與

Pattern

類一樣,

Matcher

也沒有公共構造方法。你需要調用

Pattern

對象的

matcher

方法來獲得一個

Matcher

對象。

  • PatternSyntaxException

PatternSyntaxException

是一個非強制異常類,它表示一個正規表達式模式中的文法錯誤。

以下執行個體中使用了正規表達式

.*work100.*

用于查找字元串中是否包了

work100

子串:

import java.util.regex.*;
 
class RegexExample1{
   public static void main(String[] args){
      String content = "I am xiaojun from work100.net";
 
      String pattern = ".*work100.*";
 
      boolean isMatch = Pattern.matches(pattern, content);
      System.out.println("字元串中是否包含了 'work100' 子字元串? " + isMatch);
   }
}           

執行個體輸出結果為:

字元串中是否包含了 work100 子字元串? true           

2.捕獲組

捕獲組是把多個字元當一個單獨單元進行處理的方法,它通過對括号内的字元分組來建立。

例如,正規表達式 (

dog

) 建立了單一分組,組裡包含"

d

","

o

",和"

g

捕獲組是通過從左至右計算其開括号來編号。例如,在表達式

((A)(B(C)))

,有四個這樣的組:

  • ((A)(B(C)))
  • (A)
  • (B(C))
  • (C)

可以通過調用

matcher

groupCount

方法來檢視表達式有多少個分組。

groupCount

方法傳回一個

int

值,表示

matcher

對象目前有多個捕獲組。

還有一個特殊的組(

group(0)

),它總是代表整個表達式。該組不包括在

groupCount

的傳回值中。

執行個體

下面的例子說明如何從一個給定的字元串中找到數字串:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    public static void main( String[] args ){
 
      // 按指定模式在字元串查找
      String line = "This order was placed for QT3000! OK?";
      String pattern = "(\\D*)(\\d+)(.*)";
 
      // 建立 Pattern 對象
      Pattern r = Pattern.compile(pattern);
 
      // 現在建立 matcher 對象
      Matcher m = r.matcher(line);
      if (m.find( )) {
         System.out.println("Found value: " + m.group(0) );
         System.out.println("Found value: " + m.group(1) );
         System.out.println("Found value: " + m.group(2) );
         System.out.println("Found value: " + m.group(3) ); 
      } else {
         System.out.println("NO MATCH");
      }
   }
}           

以上執行個體編譯運作結果如下:

Found value: This order was placed for QT3000! OK?
Found value: This order was placed for QT
Found value: 3000
Found value: ! OK?           

3.正規表達式文法

在其他語言中,

\\

表示:我想要在正規表達式中插入一個普通的(字面上的)反斜杠,請不要給它任何特殊的意義。

在 Java 中,

\\

表示:我要插入一個正規表達式的反斜線,是以其後的字元具有特殊的意義。

是以,在其他的語言中(如Perl),一個反斜杠

\

就足以具有轉義的作用,而在 Java 中正規表達式中則需要有兩個反斜杠才能被解析為其他語言中的轉義作用。也可以簡單的了解在 Java 的正規表達式中,兩個

\\

代表其他語言中的一個

\

,這也就是為什麼表示一位數字的正規表達式是

\\d

,而表示一個普通的反斜杠是

\\\\

字元 說明

\

将下一字元标記為特殊字元、文本、反向引用或八進制轉義符。例如,"

n

"比對字元"

n

"。"

\n

"比對換行符。序列"

\\\\

"比對"

\\

\\(

(

^

比對輸入字元串開始的位置。如果設定了

RegExp

Multiline

屬性,

^

還會與"

\n

"或"

\r

"之後的位置比對。

$

比對輸入字元串結尾的位置。如果設定了

RegExp

Multiline

$

\n

\r

"之前的位置比對。

*

零次或多次比對前面的字元或子表達式。例如,

zo*

比對"

z

"和"

zoo

*

等效于

{0,}

+

一次或多次比對前面的字元或子表達式。例如,"

zo+

"與"

zo

zoo

"比對,但與"

z

"不比對。

+

{1,}

?

零次或一次比對前面的字元或子表達式。例如,"

do(es)?

do

does

"中的"

do

?

{0,1}

{n}

n

是非負整數。正好比對

n

次。例如,"

o{2}

Bob

o

"不比對,但與"

food

"中的兩個"

o

"比對。

{n,}

n

是非負整數。至少比對

n

o{2,}

"不比對"

Bob

o

",而比對"

foooood

"中的所有

o

。"

o{1,}

"等效于"

o+

o{0,}

o*

{n,m}

m

n

是非負整數,其中

n <= m

。比對至少

n

次,至多

m

o{1,3}

fooooood

"中的頭三個

o

。'

o{0,1}

' 等效于 '

o?

'。注意:您不能将空格插入逗号和數字之間。

?

當此字元緊随任何其他限定符(

*

+

?

{n}

{n,}

{n,m}

)之後時,比對模式是"

非貪心的

非貪心的

"模式比對搜尋到的、盡可能短的字元串,而預設的"

貪心的

"模式比對搜尋到的、盡可能長的字元串。例如,在字元串"

oooo

"中,"

o+?

"隻比對單個"

o

",而"

o+

"比對所有"

o

.

比對除"

\r\n

"之外的任何單個字元。若要比對包括"

\r\n

"在内的任意字元,請使用諸如"

[\s\S]

"之類的模式。

(pattern)

比對

pattern

并捕獲該比對的子表達式。可以使用

$0…$9

屬性從結果"比對"集合中檢索捕獲的比對。若要比對括号字元

( )

,請使用"

\(

"或者"

\)

(?:pattern)

pattern

但不捕獲該比對的子表達式,即它是一個非捕獲比對,不存儲供以後使用的比對。這對于用"

or

"字元 "`(
)

"組合模式部件的情況很有用。例如,"

industr(?:y
ies)

"是比 "

industry
industries`" 更經濟的表達式。

(?=pattern)

執行正向預測先行搜尋的子表達式,該表達式比對處于比對

pattern

的字元串的起始點的字元串。它是一個非捕獲比對,即不能捕獲供以後使用的比對。例如,'`Windows (?=95
98 NT 2000)

' 比對"

Windows 2000

"中的"

Windows

",但不比對"

Windows 3.1

"中的"

Windows`"。預測先行不占用字元,即發生比對後,下一比對的搜尋緊随上一比對之後,而不是在組成預測先行的字元後。

(?!pattern)

執行反向預測先行搜尋的子表達式,該表達式比對不處于比對

pattern

的字元串的起始點的搜尋字元串。它是一個非捕獲比對,即不能捕獲供以後使用的比對。例如,'`Windows (?!95

' 比對"

"中的 "

",但不比對"

"中的"

`x y`

x

y

。例如,'`z
food

' 比對"

z

"或"

"。'

(z
f)ood

' 比對"

zood

"或"

food`"。

[xyz]

字元集。比對包含的任一字元。例如,"

[abc]

" 比對 "

plain

a

[^xyz]

反向字元集。比對未包含的任何字元。例如," "比對"plain"中"p","l","i","n"。

[a-z]

字元範圍。比對指定範圍内的任何字元。例如,"

[a-z]

a

" 到 "

z

" 範圍内的任何小寫字母。

[^a-z]

反向範圍字元。比對不在指定的範圍内的任何字元。例如,"

[^a-z]

" 比對任何不在 "

a

z

" 範圍内的任何字元。

\b

比對一個字邊界,即字與空格間的位置。例如,"

er\b

never

" 中的"

er

",但不比對"

verb

er

\B

非字邊界比對。"

er\B

verb

er

never

er

\cx

x

訓示的控制字元。例如,

\cM

Control-M

回車符

x

的值必須在

A-Z

a-z

之間。如果不是這樣,則假定

c

就是"

c

"字元本身。

\d

數字字元比對。等效于

[0-9]

\D

非數字字元比對。等效于

[^0-9]

\f

換頁符比對。等效于

\x0c

\cL

\n

換行符比對。等效于

\x0a

\cJ

\r

比對一個回車符。等效于

\x0d

\cM

\s

比對任何空白字元,包括空格、制表符、換頁符等。與

[ \f\n\r\t\v]

等效。

\S

比對任何非空白字元。與

[^ \f\n\r\t\v]

\t

制表符比對。與

\x09

\cI

\v

垂直制表符比對。與

\x0b

\cK

\w

比對任何字類字元,包括下劃線。與"

[A-Za-z0-9_]

"等效。

\W

與任何非單詞字元比對。與"

[^A-Za-z0-9_]

\xn

n

,此處的

n

是一個十六進制轉義碼。十六進制轉義碼必須正好是兩位數長。例如,"

\x41

A

\x041

\x04

"&"

1

"等效。允許在正規表達式中使用 ASCII 代碼。

\num

num

num

是一個正整數。到捕獲比對的反向引用。例如,"

(.)\1

"比對兩個連續的相同字元。

\n

辨別一個八進制轉義碼或反向引用。如果

\n

前面至少有

n

個捕獲子表達式,那麼

n

是反向引用。否則,如果

n

是八進制數

(0-7)

,那麼

n

是八進制轉義碼。

\nm

\nm

nm

nm

是反向引用。如果

\nm

n

個捕獲,則

n

是反向引用,後面跟有字元

m

。如果兩種前面的情況都不存在,則

\nm

比對八進制值

nm

,其中

n

m

是八進制數字 (

0-7

)。

\nml

n

(0-3)

m

l

是八進制數 (

0-7

) 時,比對八進制轉義碼

nml

\un

n

n

是以四位十六進制數表示的 Unicode 字元。例如,

\u00A9

比對版權符号 (

©

根據 Java Language Specification 的要求,Java 源代碼的字元串中的反斜線被解釋為 Unicode 轉義或其他字元轉義。是以必須在字元串字面值中使用兩個反斜線,表示正規表達式受到保護,不被 Java 位元組碼編譯器解釋。例如,當解釋為正規表達式時,字元串字面值 "

\b

" 與單個倒退字元比對,而 "

\\b

" 與單詞邊界比對。字元串字面值 "

\(hello\)

" 是非法的,将導緻編譯時錯誤;要與字元串

(hello)

比對,必須使用字元串字面值 "

\\(hello\\)

4.Matcher類的方法

索引方法

索引方法提供了有用的索引值,精确表明輸入字元串中在哪能找到比對:

方法及說明

public int start()

傳回以前比對的初始索引。

public int start(int group)

傳回在以前的比對操作期間,由給定組所捕獲的子序列的初始索引

public int end()

傳回最後比對字元之後的偏移量。

public int end(int group)

傳回在以前的比對操作期間,由給定組所捕獲子序列的最後字元之後的偏移量。

研究方法

研究方法用來檢查輸入字元串并傳回一個布爾值,表示是否找到該模式:

public boolean lookingAt()

嘗試将從區域開頭開始的輸入序列與該模式比對。

public boolean find()

嘗試查找與該模式比對的輸入序列的下一個子序列。

public boolean find(int start)

重置此比對器,然後嘗試查找比對該模式、從指定索引開始的輸入序列的下一個子序列。

public boolean matches()

嘗試将整個區域與模式比對。

替換方法

替換方法是替換輸入字元串裡文本的方法:

public Matcher appendReplacement(StringBuffer sb, String replacement)

實作非終端添加和替換步驟。

public StringBuffer appendTail(StringBuffer sb)

實作終端添加和替換步驟。

public String replaceAll(String replacement)

替換模式與給定替換字元串相比對的輸入序列的每個子序列。

public String replaceFirst(String replacement)

替換模式與給定替換字元串比對的輸入序列的第一個子序列。
5

public static String quoteReplacement(String s)

傳回指定字元串的字面替換字元串。這個方法傳回一個字元串,就像傳遞給

Matcher

類的

appendReplacement

方法一個字面字元串一樣工作。

start和end方法

下面是一個對單詞 "cat" 出現在輸入字元串中出現次數進行計數的例子:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    private static final String REGEX = "\\bcat\\b";
    private static final String INPUT =
                                    "cat cat cat cattie cat";
 
    public static void main(String[] args){
       Pattern p = Pattern.compile(REGEX);
       Matcher m = p.matcher(INPUT); // 擷取 matcher 對象
       int count = 0;
 
       while(m.find()) {
         count++;
         System.out.println("Match number "+count);
         System.out.println("start(): "+m.start());
         System.out.println("end(): "+m.end());
      }
   }
}           
Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
Match number 4
start(): 19
end(): 22           

可以看到這個例子是使用單詞邊界,以確定字母 "

c

" "

a

t

" 并非僅是一個較長的詞的子串。它也提供了一些關于輸入字元串中比對發生位置的有用資訊。

Start

方法傳回在以前的比對操作期間,由給定組所捕獲的子序列的初始索引,

end

方法最後一個比對字元的索引加

1

matches和lookingAt方法

matches

lookingAt

方法都用來嘗試比對一個輸入序列模式。它們的不同是

matches

要求整個序列都比對,而

lookingAt

不要求。

lookingAt

方法雖然不需要整句都比對,但是需要從第一個字元開始比對。

這兩個方法經常在輸入字元串的開始使用。

我們通過下面這個例子,來解釋這個功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    private static final String REGEX = "foo";
    private static final String INPUT = "fooooooooooooooooo";
    private static final String INPUT2 = "ooooofoooooooooooo";
    private static Pattern pattern;
    private static Matcher matcher;
    private static Matcher matcher2;
 
    public static void main( String[] args ){
       pattern = Pattern.compile(REGEX);
       matcher = pattern.matcher(INPUT);
       matcher2 = pattern.matcher(INPUT2);
 
       System.out.println("Current REGEX is: "+REGEX);
       System.out.println("Current INPUT is: "+INPUT);
       System.out.println("Current INPUT2 is: "+INPUT2);
 
       System.out.println("lookingAt(): "+matcher.lookingAt());
       System.out.println("matches(): "+matcher.matches());
       System.out.println("lookingAt(): "+matcher2.lookingAt());
   }
}           
Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
Current INPUT2 is: ooooofoooooooooooo
lookingAt(): true
matches(): false
lookingAt(): false           

replaceFirst和replaceAll方法

replaceFirst

replaceAll

方法用來替換比對正規表達式的文本。不同的是,

replaceFirst

替換首次比對,

replaceAll

替換所有比對。

下面的例子來解釋這個功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
    private static String REGEX = "dog";
    private static String INPUT = "The dog says meow. " +
                                    "All dogs say meow.";
    private static String REPLACE = "cat";
 
    public static void main(String[] args) {
       Pattern p = Pattern.compile(REGEX);
       // get a matcher object
       Matcher m = p.matcher(INPUT); 
       INPUT = m.replaceAll(REPLACE);
       System.out.println(INPUT);
   }
}           
The cat says meow. All cats say meow.           

appendReplacement和appendTail方法

Matcher

類也提供了

appendReplacement

appendTail

方法用于文本替換:

看下面的例子來解釋這個功能:

import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class RegexMatches
{
   private static String REGEX = "a*b";
   private static String INPUT = "aabfooaabfooabfoobkkk";
   private static String REPLACE = "-";
   public static void main(String[] args) {
      Pattern p = Pattern.compile(REGEX);
      // 擷取 matcher 對象
      Matcher m = p.matcher(INPUT);
      StringBuffer sb = new StringBuffer();
      while(m.find()){
         m.appendReplacement(sb,REPLACE);
      }
      m.appendTail(sb);
      System.out.println(sb.toString());
   }
}           
-foo-foo-foo-kkk           

PatternSyntaxException類的方法

PatternSyntaxException

是一個非強制異常類,它訓示一個正規表達式模式中的文法錯誤。

PatternSyntaxException

類提供了下面的方法來幫助我們檢視發生了什麼錯誤。

public String getDescription()

擷取錯誤的描述。

public int getIndex()

擷取錯誤的索引。

public String getPattern()

擷取錯誤的正規表達式模式。

public String getMessage()

傳回多行字元串,包含文法錯誤及其索引的描述、錯誤的正規表達式模式和模式中錯誤索引的可視化訓示。

上一篇:

日期時間

下一篇:

方法
如果對課程内容感興趣,可以掃碼關注我們的

公衆号

QQ群

,及時關注我們的課程更新
Java入門 - 語言基礎 - 18.正規表達式正規表達式
Java入門 - 語言基礎 - 18.正規表達式正規表達式
  1. abc