JavaRush /Java Blog /Random-TW /Java 中的正規表示式,第 2 部分

Java 中的正規表示式,第 2 部分

在 Random-TW 群組發布
我們向您展示 Java 正規表示式簡短指南的翻譯,該指南由 Jeff Friesen 為javaworld網站編寫。為了方便閱讀,我們將文章分成幾個部分。 Java 中的正規表示式,第 2 部分 - 1Java 中的正規表示式,第 1 部分
合併多個範圍
您可以透過並排放置多個範圍將它們合併到單一範圍字元類別中。例如,該類別[a-zA-Z]會匹配所有小寫或大寫的拉丁字母字元。

合併多個範圍

您可以透過並排放置多個範圍將它們合併到單一範圍字元類別中。例如,該類別[a-zA-Z]會匹配所有小寫或大寫的拉丁字母字元。

組合字元類

字元類別聯合由多個嵌套字元類別組成,並匹配生成的聯合中的所有字元。例如,該類別[a-d[m-p]]匹配字元 from atod和 from mto p。考慮以下範例: 此範例將尋找、、和,其中 中存在相符的java RegexDemo [ab[c-e]] abcdef 字元 、、和: abcdeabcdef
regex = [ab[c-e]]
input = abcdef
Found [a] starting at 0 and ending at 0
Found [b] starting at 1 and ending at 1
Found [c] starting at 2 and ending at 2
Found [d] starting at 3 and ending at 3
Found [e] starting at 4 and ending at 4

字符類交集

字元類別的交集由所有嵌套類別共有的字元組成,並且僅匹配公共字元。例如,該類別[a-z&&[d-f]]匹配字元d,ef。請考慮以下範例: java RegexDemo "[aeiouy&&[y]]" party 請注意,在我的 Windows 作業系統上,需要雙引號,因為命令 shell 將它們視為&命令分隔符號。y此範例將僅查找在 中符合的字元party
regex = [aeiouy&&[y]]
input = party
Found [y] starting at 4 and ending at 4

減去字元類

減去字元類別由除嵌套字元類別中包含的字元之外的所有字元組成,並且僅匹配那些剩餘的字元。例如,該類別[a-z&&[^m-p]]匹配字元 from atol和 from qto z: 此範例將查找在 中匹配的java RegexDemo "[a-f&&[^a-c]&&[^e]]" abcdefg 字元d和: fabcdefg
regex = [a-f&&[^a-c]&&[^e]]
input = abcdefg
Found [d] starting at 3 and ending at 3
Found [f] starting at 5 and ending at 5

預定義字元類

某些字元類別在正規表示式中出現的頻率足夠高,足以證明使用簡寫符號是合理的。此類別Pattern提供預先定義的字元類別作為此類縮寫。您可以使用它們來簡化正規表示式並最大限度地減少語法錯誤。預定義字元類別有多種類別:標準、POSIXjava.lang.Character和 Unicode 屬性,例如腳本、區塊、類別和二進位。以下列表僅顯示標準類別的類別:
  • \d: 數字。相等的[0-9]
  • \D: 非數字字元。相等的[^0-9]
  • \s:空白字元。相等的[ \t\n\x0B\f\r]
  • \S: 不是空白字元。相等的[^\s]
  • \w:構詞符號。相等的[a-zA-Z_0-9]
  • \W: 不是構詞字元。相等的[^\w]
以下範例使用預先定義的字元類別\w來描述輸入文字中的所有單字字元: java RegexDemo \w "aZ.8 _" 仔細觀察以下執行結果,可以看出句點和空格字元不被視為單字字元:
regex = \w
input = aZ.8 _
Found [a] starting at 0 and ending at 0
Found [Z] starting at 1 and ending at 1
Found [8] starting at 3 and ending at 3
Found [_] starting at 5 and ending at 5
行分隔符
類 SDK 文件Pattern將點元字元描述為預先定義的字元類,它會匹配除行分隔符號(標記行結尾的一個或兩個字元序列)之外的任何字元。dotall 模式是個例外(我們將在接下來討論),其中點也與行分隔符號相符。該類別區分Pattern以下行分隔符號:
  • 回車符 ( \r);
  • 換行符(紙張前進一行的符號)( \n);
  • 回車符後緊接換行符 ( \r\n);
  • 下一行字元 ( \u0085);
  • 行分隔符號 ( \u2028);
  • 段落分隔符號 ( \u2029)

捕獲的群體

捕獲組用於保存找到的字元集,以便在按模式搜尋時進一步使用。此構造是用括號 ( ) 括在元字元中的字元序列( )。按模式搜尋時,捕獲組中的所有字元都被視為一個整體。例如,捕獲組 ( Java) 將字母Jav和組合a成一個單元。Java此捕獲組會尋找輸入文字中出現的所有模式。每次符合時,先前儲存的字元Java都會被下一個字元取代。捕獲的組可以嵌套在其他捕獲的組中。例如,在正規表示式中,(Java( language))群組(language)嵌套在群組內(Java)。每個嵌套或非嵌套捕獲組都分配編號,從 1 開始,從左到右編號。在前面的範例中,(Java( language))匹配捕獲組編號 1 並(language)匹配捕獲組編號 2。在正則表達式 中(a)(b)(a)匹配捕獲組編號 1 和(b)捕獲組編號 2。 Java 中的正規表示式,第 2 部分 - 2稍後可以使用反向引用訪問捕獲組存儲的匹配項。反向引用指定為反斜線字符後跟與正在捕獲的組的編號相對應的數字字符,允許您引用該組捕獲的文本中的字符。具有反向連結會導致匹配器根據捕獲的群組中的數字引用其儲存的搜尋結果,然後使用該結果中的字元來嘗試進一步搜尋。以下範例顯示如何使用反向引用來尋找文字中的語法錯誤: java RegexDemo "(Java( language)\2)" "The Java language language" 此範例使用正規表示式來尋找輸入文字中緊接著的(Java( language)\2)重複單字的語法錯誤。此正規表示式指定要捕獲的兩個群組:數字 1 –對應於,數字 2 –對應於後面的空格字元。後向引用允許重新存取群組編號 2 的儲存結果,以便匹配器可以在第一次出現空格和 後搜尋第二次出現的空格,後面接著。匹配器的結果如下: languageJava"The Java language language"(Java( language)\2)Java language language(language)language\2languagelanguageRegexDemo
regex = (Java( language)\2)
input = The Java language language
Found [Java language language] starting at 4 and ending at 25

邊界匹配器

有時您需要在行首、單字邊界、文字結尾等執行模式匹配。您可以使用邊緣匹配器類別之一來執行此操作Pattern,這些匹配器是正規表示式構造,可在以下位置搜尋匹配項:
  • ^:行首;
  • $: 行結束;
  • \b:字邊界;
  • \B:偽字邊界;
  • \A:文本開始;
  • \G:上一場比賽結束;
  • \Z:文字結束,不包括尾隨行分隔符號(如果存在);
  • \z: 正文結束
以下範例使用^邊界匹配器元字元查找以 開頭The,後面可以跟零個或多個單字字元的行: java RegexDemo "^The\w*" Therefore 該字元^指定輸入文字的前三個字元必須與連續的模式字元Th和匹配e,後面可以跟任意數字的構詞符號。這是執行結果:
regex = ^The\w*
input = Therefore
Found [Therefore] starting at 0 and ending at 8
如果將命令列更改為 會發生什麼java RegexDemo "^The\w*" " Therefore"Therefore由於輸入文字前面有空格字符,因此 找不到匹配項。

零長度匹配

有時,在使用邊緣匹配器時,您會遇到零長度匹配。Совпадение нулевой длины是不包含任何字元的匹配。它們可以出現在空輸入文字中、輸入文字的開頭、輸入文字的最後一個字元之後以及輸入文字的任兩個字元之間。零長度匹配很容易識別,因為它們總是在同一位置開始和結束。考慮以下範例: java RegExDemo \b\b "Java is" 此範例搜尋兩個連續的單字邊界,結果如下所示:
regex = \b\b
input = Java is
Found [] starting at 0 and ending at -1
Found [] starting at 4 and ending at 3
Found [] starting at 5 and ending at 4
Found [] starting at 7 and ending at 6
我們在結果中看到幾個零長度匹配。這裡的結束位置比起始位置少 1,因為RegexDemo我在 清單 1 的原始碼中指定了end() – 1Java 中的正規表示式,第 2 - 3 部分

量詞

量詞是一種正規表示式構造,它明確或隱式地將模式與數值關聯起來。此數值決定搜尋模式的次數。量詞分為貪婪量詞、懶量詞、超貪婪量詞:
  • 貪婪量詞(?*+)旨在尋找最長匹配。請問X?尋找一次或更少的出現次數XX*查找零次或多次出現次數XX+查找一次或多次出現次數XX{n}查找次數、查找至少(並且可能更多)次出現次數以及查找至少但不多次出現次數。nXX{n,}nXX{n,m}nmX
  • 惰性量詞(??,*?+?)旨在查找最短匹配。您可以指定X??搜尋 1 次或更少出現的X, X*? 尋找零個或多個出現的情況XX+?尋找一個或多個出現的情況XX{n}?尋找n出現的情況XX{n,}?尋找至少(可能有更多)n出現的情況X以及X{n,m}?尋找至少n但不超過m出現的情況X
  • 超貪婪量詞(?+*+++)與貪婪量詞類似,不同之處在於超貪婪量詞僅嘗試一次來查找最長匹配,而貪婪量詞可以進行多次嘗試。可以設定X?+為查找 1 次或更少的出現次數XX*+查找0 次或多次出現次數XX++查找 1 次或多次出現次數X、查找 的出現次數、查找至少(也可能更多)次出現次數以及查找至少但不超過1 個出現次數。X{n}+nXX{n,}+nXX{n,m}+ nmX
以下範例說明了貪婪量詞的使用: java RegexDemo .*ox "fox box pox" 以下是結果:
regex = .*ox
input = fox box pox
Found [fox box pox] starting at 0 and ending at 10
貪婪量詞 ( .*) 找出以 結尾的最長字元序列ox。它會消耗整個輸入文本,然後回滾,直到檢測到輸入文本以這些字符結尾。現在讓我們來看看惰性量詞: java RegexDemo .*?ox "fox box pox" 它的結果:
regex = .*?ox
input = fox box pox
Found [fox] starting at 0 and ending at 2
Found [ box] starting at 3 and ending at 6
Found [ pox] starting at 7 and ending at 10
惰性量詞 ( .*?) 找出以 結尾的最短字元序列ox。它以空白字串開始,逐漸消耗字符,直到找到匹配項。然後繼續工作,直到輸入文字用完。最後,讓我們來看看超貪婪量詞: java RegexDemo .*+ox "fox box pox" 這是它的結果:
regex = .*+ox
input = fox box pox
超貪婪量詞 ( .*+) 找不到匹配項,因為它消耗了所有輸入文本,並且正則ox表達式末尾沒有任何內容可匹配。與貪婪量詞不同,超貪婪量詞不會回滾。

零長度匹配

有時,在使用量詞時,您會遇到零長度匹配。例如,使用以下貪婪量詞會導致多個零長度匹配: java RegexDemo a? abaa 運行此範例的結果:
regex = a?
input = abaa
Found [a] starting at 0 and ending at 0
Found [] starting at 1 and ending at 0
Found [a] starting at 2 and ending at 2
Found [a] starting at 3 and ending at 3
Found [] starting at 4 and ending at 3
執行結果中有5個匹配項。a雖然第一、第三和第四個是相當意料之中的(它們對應於中三個字母的位置abaa),但第二個和第五個可能會讓你感到驚訝。看起來好像它們表明了與文本結尾a相對應的b內容,但實際上並非如此。正規表示式a?不會b在文字末尾進行搜尋。它搜尋存在或不存在a。當a?它沒有找到時a,它會將其報告為零長度匹配。

嵌套標誌表達式

匹配器會做出一些預設假設,在將正規表示式編譯為模式時可以覆寫這些預設假設。我們稍後再討論這個問題。正規表示式可讓您使用嵌套標誌表達式覆寫任何預設值。此正規表示式構造被指定為問號元字符 ( ) 周圍的括號元字符?,後面跟著一個小寫拉丁字母。該類別Pattern理解以下嵌套標誌表達式:
  • (?i):啟用不區分大小寫的模式匹配。例如,使用命令時,java RegexDemo (?i)tree Treehouse字元序列Tree與模式相符tree。預設是區分大小寫的模式搜尋。
  • (?x):允許在模式中使用以元字元開頭的空白字元和註解#。匹配器將忽略兩者。例如,對於匹配模式java RegexDemo ".at(?x)#match hat, cat, and so on" matter的字元序列。預設情況下,不允許使用空格字元和註釋,匹配器將它們視為搜尋中涉及的字元。mat.at
  • (?s):啟用 dotall 模式,在該模式下,點元字元除了匹配任何其他字元外,還匹配行分隔符號。例如,該命令java RegexDemo (?s). \n將查找換行符。預設值與 dotall 相反:不會找到行分隔符號。例如,該命令Java RegexDemo . \n將找不到換行符。
  • (?m):啟用多行模式,以符合每行的^開頭和$結尾。例如,java RegexDemo "(?m)^abc$" abc\nabc在輸入文字中尋找兩個序列abc。預設情況下,使用單行模式:^匹配整個輸入文字的開頭,並$匹配其結尾。例如,java RegexDemo "^abc$" abc\nabc傳回沒有匹配項的回應。
  • (?u):啟用 Unicode 敏感的大小寫對齊。此標誌與 結合使用時(?i),允許根據 Unicode 標準進行不區分大小寫的模式匹配。預設設定是僅搜尋區分大小寫和 US-ASCII 字元。
  • (?d):啟用 Unix 風格的字串模式,其中匹配器識別上下文中的元字符.^並且$僅識別行分隔符\n。預設是非 Unix 風格的字串模式:匹配器在上述元字元的上下文中識別所有行分隔符號。
嵌套標誌表達式類似於捕獲的組,因為它們的字元被括號元字元包圍。與捕獲組不同,嵌套標誌表達式是非捕獲組的範例,非捕獲組是不捕獲文字字元的正規表示式構造。它們被定義為由括號元字元包圍的字元序列。
指定多個嵌套標誌表達式
可以在正規表示式中指定多個嵌套標誌表達式,方法是將它們並排放置 ( (?m)(?i))) 或按順序放置定義它們的字母 ( (?mi))。

結論

現在您可能已經意識到,正規表示式非常有用,並且當您掌握其語法的細微差別時,它會變得更加有用。到目前為止,我已經向您介紹了正規表示式和Pattern. Pattern在第 2 部分中,我們將深入研究 Regex API 並探索,Matcher和的方法PatternSyntaxException。我還將向您展示 Regex API 的兩個實際應用程序,您可以立即在程式中使用它們。 Java 中的正規表示式,第 3 部分 Java 中的正規表示式,第 4 部分 Java 中的正規表示式,第 5 部分
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION