柚子快報(bào)激活碼778899分享:認(rèn)真來看下正則表達(dá)式
柚子快報(bào)激活碼778899分享:認(rèn)真來看下正則表達(dá)式
目錄
一、簡(jiǎn)單談?wù)務(wù)齽t
二、基礎(chǔ)知識(shí)學(xué)習(xí)
(一)正則元字符
1.特殊單字符
2.空白符
3.量詞
4.范圍備和選項(xiàng)
綜合練習(xí)
(二)貪婪、非貪婪與獨(dú)占模式
1.貪婪模式
2.非貪婪模式(懶惰模式)
3.獨(dú)占模式
(三)分組與引用
1.捕獲分組(Capturing Group)
2.非捕獲分組(Non-Capturing Group)
3.命名捕獲分組(Named Capturing Group)
4. 引用(Backreference)
5. 重復(fù)分組
(四)匹配模式
1.不區(qū)分大小寫
2.點(diǎn)號(hào)通配模式
3.多行模式
4.注釋模式
(五)斷言(Assertion)
1.單詞的邊界
2.行的開始或結(jié)束
3.環(huán)視(Lookaround)
(六)正則轉(zhuǎn)義
干貨分享,感謝您的閱讀!
一、簡(jiǎn)單談?wù)務(wù)齽t
正則,也稱為正則表達(dá)式(Regular Expression),是一種用于文本匹配和搜索的強(qiáng)大工具。它是一種由字符和特殊符號(hào)組成的字符串模式,用于描述和匹配一組文本字符串,而不是固定的字符串。正則表達(dá)式可以做以下事情:
正則表達(dá)式的語法和規(guī)則因編程語言和庫的不同而有所差異,但它們?cè)谔幚砦谋緮?shù)據(jù)時(shí)都具有廣泛的應(yīng)用。學(xué)習(xí)正則表達(dá)式可以提高文本處理和數(shù)據(jù)提取的效率,但也需要花一些時(shí)間來掌握它們的復(fù)雜性。不同編程語言和工具提供不同的正則表達(dá)式支持,所以你需要查閱相應(yīng)的文檔來學(xué)習(xí)如何在特定環(huán)境中使用正則表達(dá)式。
當(dāng)前寫的正則可以直接在線驗(yàn)證:正則表達(dá)式在線測(cè)試 | 菜鳥工具
二、基礎(chǔ)知識(shí)學(xué)習(xí)
(一)正則元字符
1.特殊單字符
當(dāng)描述正則表達(dá)式中的特殊單字符元字符時(shí),可以整合為一個(gè)表格,如下所示:
元字符描述示例.匹配除換行符 \n 之外的任何單個(gè)字符。"c.t" 可以匹配 "cat"、"cut"、"c@t" 等\d匹配任何單個(gè)數(shù)字(0-9)。"The answer is 42" 中的 \d 可以匹配 "4" 和 "2"\w匹配任何單個(gè)字母、數(shù)字或下劃線字符(單詞字符)。"word_123" 中的 \w 可以匹配 "w"、"o"、"r"、"d"、"1"、"2"、"3" 和 "_"\s匹配任何單個(gè)空白字符,包括空格、制表符、換行符等。"Hello\tworld\n" 中的 \s 可以匹配制表符和換行符\D匹配任何非數(shù)字字符。"Hello, World!" 中的 \D 可以匹配 ","、"H"、"e"、"l"、"l"、"o"、" "、"W" 等\W匹配任何非單詞字符。"text-with-hyphen" 中的 \W 可以匹配 "-"\S匹配任何非空白字符。"This is text" 中的 \S 可以匹配 "T"、"h"、"i"、"s"、"i"、"s"、"t"、"e"、"x"、"t"
這個(gè)表格提供了有關(guān)這些特殊單字符元字符的簡(jiǎn)明描述以及示例用法,有助于理解它們的用途和功能。在實(shí)際使用正則表達(dá)式時(shí),可以根據(jù)需要結(jié)合這些元字符來構(gòu)建匹配模式。
我們使用java驗(yàn)證以上內(nèi)容如下:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 特殊單字符元字符驗(yàn)證
* @author: zhangyanfeng
* @create: 2023-11-05 00:04
**/
public class SpecialSingleCharRegexExample {
public static void main(String[] args) {
// 使用正則表達(dá)式驗(yàn)證特殊單字符元字符
// 創(chuàng)建匹配器
MatcherWithInfo("1. Matches for 'c.t'", "cat cut c@t", "c.t");
MatcherWithInfo("2. Matches for '\\d'", "The answer is 42", "\\d");
MatcherWithInfo("3. Matches for '\\w'", "word_123", "\\w");
MatcherWithInfo("4. Matches for '\\s'", "Hello\tworld\n", "\\s");
// 反義元字符
MatcherWithInfo("5. Matches for '\\D'", "Hello, World!", "\\D");
MatcherWithInfo("6. Matches for '\\W'", "text-with-hyphen", "\\W");
MatcherWithInfo("7. Matches for '\\S'", "This is text", "\\S");
}
// 匹配器并打印結(jié)果
private static void MatcherWithInfo(String header, String text, String regex) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
StringBuilder matches = new StringBuilder();
while (matcher.find()) {
matches.append(matcher.group()).append(" ");
}
System.out.println(header);
System.out.println(" Original Text: " + text);
System.out.println(" Matching Result: " + (matches.length() > 0 ? matches.toString().trim() : "No Match"));
System.out.println();
}
}
驗(yàn)證結(jié)果如下:
1. Matches for 'c.t'
Original Text: cat cut c@t
Matching Result: cat cut c@t
2. Matches for '\d'
Original Text: The answer is 42
Matching Result: 4 2
3. Matches for '\w'
Original Text: word_123
Matching Result: w o r d _ 1 2 3
4. Matches for '\s'
Original Text: Hello world
Matching Result:
5. Matches for '\D'
Original Text: Hello, World!
Matching Result: H e l l o , W o r l d !
6. Matches for '\W'
Original Text: text-with-hyphen
Matching Result: - -
7. Matches for '\S'
Original Text: This is text
Matching Result: T h i s i s t e x t
2.空白符
在正則表達(dá)式中,空白符通常表示為轉(zhuǎn)義序列,用于匹配文本中的空格、制表符、換行符等空白字符。以下是一些常見的空白符的表示方式和它們的含義:
元字符描述\s匹配任何單個(gè)空白字符,包括空格、制表符、換行符、回車符和換頁符等。\t匹配制表符(Tab)字符。\n匹配換行符(newline),用于表示文本中的新行。\r匹配回車符(carriage return),通常用于控制光標(biāo)的位置。\f匹配換頁符(form feed),通常用于分頁打印。\v匹配垂直制表符(vertical tab)。\h匹配水平空白符(horizontal whitespace),包括空格和制表符。\v匹配垂直空白符(vertical whitespace),包括換行符、回車符等。\S匹配任何單個(gè)非空白字符,與\s 的作用相反。
這些轉(zhuǎn)義字符可以用于構(gòu)建正則表達(dá)式模式,以匹配特定類型的空白符或在文本中查找空白字符。根據(jù)需求,可以選擇使用這些轉(zhuǎn)義字符來處理文本中的空白符。
我們使用java驗(yàn)證以上內(nèi)容如下:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 驗(yàn)證和打印正則表達(dá)式空白符元字符
* @author: zhangyanfeng
* @create: 2023-11-05 12:21
**/
public class WhitespaceRegexExample {
public static void main(String[] args) {
// 使用正則表達(dá)式驗(yàn)證空白符元字符
// 創(chuàng)建匹配器并打印結(jié)果
MatcherWithInfo("1. Matches for '\\s':", "This is some text with spaces and tabs.", "\\s");
MatcherWithInfo("2. Matches for '\\t':", "Tab\tSeparated\tText", "\\t");
MatcherWithInfo("3. Matches for '\\n':", "Newline\nSeparated\nText", "\\n");
MatcherWithInfo("4. Matches for '\\r':", "Carriage\rReturn", "\\r");
MatcherWithInfo("5. Matches for '\\f':", "Form\fFeed", "\\f");
MatcherWithInfo("6. Matches for '\\v':", "Vertical\\vTab", "\\v");
MatcherWithInfo("7. Matches for '\\h':", "Horizontal hWhitespace hExample", "\\h");
MatcherWithInfo("8. Matches for '\\v':", "Vertical vWhitespace vExample", "\\v");
MatcherWithInfo("9. Matches for '\\S':", "This_is_non-space_text", "\\S");
}
// 匹配器并打印結(jié)果
private static void MatcherWithInfo(String header, String text, String regex) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
StringBuilder matches = new StringBuilder();
while (matcher.find()) {
matches.append(matcher.group()).append(" ");
}
System.out.println(header);
System.out.println(" Original Text: " + text);
System.out.println(" Matching Result: " + (matches.length() > 0 ? matches.toString().trim() : "No Match"));
System.out.println();
}
}
驗(yàn)證結(jié)果如下:
1. Matches for '\s':
Original Text: This is some text with spaces and tabs.
Matching Result:
2. Matches for '\t':
Original Text: Tab Separated Text
Matching Result:
3. Matches for '\n':
Original Text: Newline
Separated
Text
Matching Result:
4. Matches for '\r':
Return
Matching Result:
5. Matches for '\f':
Original Text: FormFeed
Matching Result:
6. Matches for '\v':
Original Text: Vertical\vTab
Matching Result: No Match
7. Matches for '\h':
Original Text: Horizontal hWhitespace hExample
Matching Result:
8. Matches for '\v':
Original Text: Vertical vWhitespace vExample
Matching Result: No Match
9. Matches for '\S':
Original Text: This_is_non-space_text
Matching Result: T h i s _ i s _ n o n - s p a c e _ t e x t
3.量詞
量詞是正則表達(dá)式中的元字符,用于指定某個(gè)部分的重復(fù)次數(shù)。它們?cè)试S匹配單個(gè)字符或模式的重復(fù)出現(xiàn),從零次到多次。以下是一些常見的量詞元字符及其含義:
元字符描述示例*匹配前面的元素零次或多次。a* 匹配 "a"、"aa"、"aaa" 等。+匹配前面的元素至少一次或多次。b+ 匹配 "b"、"bb"、"bbb" 等。?匹配前面的元素零次或一次。c? 匹配 "c" 或空字符串。{m}匹配前面的元素精確 m 次。d{3} 匹配 "ddd"。{m,}匹配前面的元素至少 m 次。e{2,} 匹配 "ee"、"eee" 等。{m,n}匹配前面的元素 m 到 n 次,包括 m 和 n。f{1,3} 匹配 "f"、"ff"、"fff"。
這些量詞元字符使你能夠更靈活地定義正則表達(dá)式,以匹配不同數(shù)量的字符或模式。它們對(duì)于匹配重復(fù)出現(xiàn)的文本模式非常有用,如匹配電話號(hào)碼、日期、電子郵件地址等。
我們使用java驗(yàn)證以上內(nèi)容如下:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 驗(yàn)證正則表達(dá)式量詞元字符
* @author: zhangyanfeng
* @create: 2023-11-05 12:34
**/
public class QuantifierRegexExample {
public static void main(String[] args) {
// 使用正則表達(dá)式驗(yàn)證量詞元字符
// 創(chuàng)建匹配器并打印結(jié)果
MatcherWithInfo("1. Matches for 'a*':", "aaaabb", "a*");
MatcherWithInfo("2. Matches for 'b+':", "aaaabb", "b+");
MatcherWithInfo("3. Matches for 'c?':", "aaaabb", "c?");
MatcherWithInfo("4. Matches for 'd{3}':", "aaadddbb", "d{3}");
MatcherWithInfo("5. Matches for 'e{2,}':", "eeeefbb", "e{2,}");
MatcherWithInfo("6. Matches for 'f{1,3}':", "ffbbfffb", "f{1,3}");
}
// 匹配器并打印結(jié)果
private static void MatcherWithInfo(String header, String text, String regex) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
StringBuilder matches = new StringBuilder();
while (matcher.find()) {
matches.append(matcher.group()).append(" ");
}
System.out.println(header);
System.out.println(" Original Text: " + text);
System.out.println(" Matching Result: " + (matches.length() > 0 ? matches.toString().trim() : "No Match"));
System.out.println();
}
}
驗(yàn)證結(jié)果如下:
1. Matches for 'a*':
Original Text: aaaabb
Matching Result: aaaa
2. Matches for 'b+':
Original Text: aaaabb
Matching Result: bb
3. Matches for 'c?':
Original Text: aaaabb
Matching Result:
4. Matches for 'd{3}':
Original Text: aaadddbb
Matching Result: ddd
5. Matches for 'e{2,}':
Original Text: eeeefbb
Matching Result: eeee
6. Matches for 'f{1,3}':
Original Text: ffbbfffb
Matching Result: ff fff
4.范圍備和選項(xiàng)
范圍元字符用于匹配特定范圍內(nèi)的字符或數(shù)字。它們?cè)试S你指定一個(gè)字符或數(shù)字必須在某個(gè)范圍內(nèi)才能匹配成功。以下是常見的范圍元字符及其含義:
范圍元字符描述示例|表示或的關(guān)系通常用于選擇多個(gè)備選項(xiàng)之一"apple|banana|cherry"將匹配文本中包含 "apple"、"banana" 或 "cherry" 中的任何一個(gè)[]方括號(hào)內(nèi)放置字符范圍,表示匹配方括號(hào)中列出的任何字符。[aeiou] 匹配元音字母 "a"、"e"、"i"、"o" 或 "u" 中的任何一個(gè)。[a-z]在方括號(hào)內(nèi)使用連字符 - 表示一個(gè)字符范圍,匹配從 "a" 到 "z" 之間的任何小寫字母。[a-z] 匹配任何小寫字母。[A-Z]類似地,匹配從 "A" 到 "Z" 之間的任何大寫字母。[A-Z] 匹配任何大寫字母。[0-9]匹配從 "0" 到 "9" 之間的任何數(shù)字。[0-9] 匹配任何數(shù)字。[^]在方括號(hào)內(nèi)放置字符范圍的開頭使用脫字符 ^ 表示反義,即匹配不在方括號(hào)中列出的字符。[^aeiou] 匹配任何非元音字母。
這些范圍元字符非常有用,因?yàn)樗鼈冊(cè)试S你精確地定義要匹配的字符范圍,從而更靈活地處理不同類型的文本。
添加管道符 | 表示或的關(guān)系通常用于選擇多個(gè)備選項(xiàng)之一,而不是范圍元字符的一部分。范圍元字符主要用于指定字符范圍,而 | 主要用于選擇不同的模式或備選項(xiàng)。
String regex = "apple|banana|cherry";
這將匹配文本中包含 "apple"、"banana" 或 "cherry" 中的任何一個(gè)。
總結(jié)來說,[] 是用于定義字符范圍的元字符,而 | 是用于選擇多個(gè)備選項(xiàng)之一的元字符。這兩者在正則表達(dá)式中有不同的用途。
我們使用java驗(yàn)證以上內(nèi)容如下:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 驗(yàn)證正則表達(dá)式中的范圍元字符和備選項(xiàng)
* @author: zhangyanfeng
* @create: 2023-11-05 13:39
**/
public class RangeRegexExample {
public static void main(String[] args) {
// 使用正則表達(dá)式驗(yàn)證范圍元字符和備選項(xiàng)
// 創(chuàng)建匹配器并打印結(jié)果
MatcherWithInfo("1. Matches for '[aeiou]':", "Hello, world!", "[aeiou]");
MatcherWithInfo("2. Matches for '[a-z]':", "The quick brown fox", "[a-z]");
MatcherWithInfo("3. Matches for '[0-9]':", "12345 and 67890", "[0-9]");
MatcherWithInfo("4. Matches for 'apple|banana|cherry':", "I like cherry pie.", "apple|banana|cherry");
MatcherWithInfo("5. Matches for '[^aeiou]':", "This is a test.", "[^aeiou]");
}
// 匹配器并打印結(jié)果
private static void MatcherWithInfo(String header, String text, String regex) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
StringBuilder matches = new StringBuilder();
while (matcher.find()) {
matches.append(matcher.group()).append(" ");
}
System.out.println(header);
System.out.println(" Original Text: " + text);
System.out.println(" Matching Result: " + (matches.length() > 0 ? matches.toString().trim() : "No Match"));
System.out.println();
}
}
驗(yàn)證結(jié)果如下:
1. Matches for '[aeiou]':
Original Text: Hello, world!
Matching Result: e o o
2. Matches for '[a-z]':
Original Text: The quick brown fox
Matching Result: h e q u i c k b r o w n f o x
3. Matches for '[0-9]':
Original Text: 12345 and 67890
Matching Result: 1 2 3 4 5 6 7 8 9 0
4. Matches for 'apple|banana|cherry':
Original Text: I like cherry pie.
Matching Result: cherry
5. Matches for '[^aeiou]':
Original Text: This is a test.
Matching Result: T h s s t s t .
綜合練習(xí)
當(dāng)使用正則表達(dá)式來表示手機(jī)號(hào)時(shí),可以按照你提供的規(guī)則,編寫一個(gè)更嚴(yán)謹(jǐn)?shù)恼齽t表達(dá)式。根據(jù)你的規(guī)則,手機(jī)號(hào)的格式可以表示為 1[3456789]\d{9},其中:
1 表示第1位固定為數(shù)字1。[3456789] 表示第2位可以是數(shù)字3、4、5、6、7、8或9中的任何一個(gè)。\d{9} 表示第3位到第11位可以是0-9中的任意數(shù)字,并且總共需要匹配9個(gè)數(shù)字。
下面是一個(gè)使用該正則表達(dá)式的 Java 示例:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 手機(jī)號(hào)的格式可以表示為 1[3456789]\d{9}
* @author: zhangyanfeng
* @create: 2023-11-05 13:59
**/
public class PhoneNumberValidation {
public static void main(String[] args) {
String regex = "1[3456789]\\d{9}";
String[] phoneNumbers = {
"13912345678",
"18887654321",
"12345678901",
"135",
"1891234",
"158888888888"
};
for (String phoneNumber : phoneNumbers) {
boolean isMatch = validatePhoneNumber(phoneNumber, regex);
System.out.println(phoneNumber + " is a valid phone number: " + isMatch);
}
}
private static boolean validatePhoneNumber(String phoneNumber, String regex) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(phoneNumber);
return matcher.matches();
}
}
驗(yàn)證結(jié)果如下:
13912345678 is a valid phone number: true
18887654321 is a valid phone number: true
12345678901 is a valid phone number: false
135 is a valid phone number: false
1891234 is a valid phone number: false
158888888888 is a valid phone number: false
(二)貪婪、非貪婪與獨(dú)占模式
在正則表達(dá)式中,貪婪、非貪婪和獨(dú)占模式是用來控制量詞(如 *、+、?、{n,m} 等)的匹配方式的不同選項(xiàng)。它們影響了正則表達(dá)式的匹配行為,以及在發(fā)現(xiàn)多個(gè)匹配時(shí)如何選擇。這些模式用于控制量詞的匹配方式,根據(jù)不同的需求和性能考慮,可以選擇使用貪婪、非貪婪或獨(dú)占模式來匹配文本。通常,貪婪模式是默認(rèn)的,非貪婪模式和獨(dú)占模式用于更精確地控制匹配行為。
1.貪婪模式
婪模式是默認(rèn)的模式,它會(huì)盡可能多地匹配文本,使量詞匹配盡量多的字符。例如,正則表達(dá)式 a+ 貪婪地匹配盡可能多的連續(xù)字符 "a" 直到找不到更多的 "a" 為止。
貪婪模式通常在需要匹配盡可能多的文本時(shí)使用。以下是一些使用貪婪模式的實(shí)際案例分析:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用貪婪模式的實(shí)際案例分析
* @author: zhangyanfeng
* @create: 2023-11-05 14:14
**/
public class GreedyExample {
public static void main(String[] args) {
// 案例 1: 提取段落文本
String paragraphText = "
段落 1
段落 2
段落 3
";Pattern paragraphPattern = Pattern.compile("
(.*?)
");Matcher paragraphMatcher = paragraphPattern.matcher(paragraphText);
System.out.println("案例 1: 提取段落文本\n文本: " + paragraphText);
int paragraphNumber = 1;
while (paragraphMatcher.find()) {
String paragraph = paragraphMatcher.group(1);
System.out.println("段落 " + paragraphNumber + ": " + paragraph);
paragraphNumber++;
}
// 案例 2: 提取注釋內(nèi)容
String code = "/* 這是一個(gè)注釋 */ int x = 10; /* 另一個(gè)注釋 */";
Pattern commentPattern = Pattern.compile("/\\*(.*?)\\*/");
Matcher commentMatcher = commentPattern.matcher(code);
System.out.println("\n案例 2: 提取注釋內(nèi)容\n代碼: " + code);
while (commentMatcher.find()) {
String comment = commentMatcher.group(1);
System.out.println("注釋: " + comment);
}
// 案例 3: 匹配 HTML 標(biāo)簽
String htmlText = "
Pattern htmlPattern = Pattern.compile("<(.*?)>");
Matcher htmlMatcher = htmlPattern.matcher(htmlText);
System.out.println("\n案例 3: 匹配 HTML 標(biāo)簽\nHTML 文本: " + htmlText);
while (htmlMatcher.find()) {
String htmlTag = htmlMatcher.group(1);
System.out.println("HTML 標(biāo)簽: " + htmlTag);
}
}
}
驗(yàn)證結(jié)果展示:
案例 1: 提取段落文本
文本:
段落 1
段落 2
段落 3
段落 1: 段落 1
段落 2: 段落 2
段落 3: 段落 3
案例 2: 提取注釋內(nèi)容
代碼: /* 這是一個(gè)注釋 */ int x = 10; /* 另一個(gè)注釋 */
注釋: 這是一個(gè)注釋
注釋: 另一個(gè)注釋
案例 3: 匹配 HTML 標(biāo)簽
HTML 文本:
HTML 標(biāo)簽: div class="container"
HTML 標(biāo)簽: span
HTML 標(biāo)簽: /span
HTML 標(biāo)簽: /div
貪婪模式通常用于需要匹配完整塊的情況,它會(huì)盡可能多地匹配文本,以便提取完整的內(nèi)容。然而,需要謹(jǐn)慎使用貪婪模式,以避免匹配過多的文本,導(dǎo)致匹配不符合預(yù)期。在特定情況下,非貪婪模式或獨(dú)占模式可能更合適。
2.非貪婪模式(懶惰模式)
?非貪婪模式允許最小匹配,它會(huì)盡可能少地匹配文本。非貪婪模式使用 ? 后綴來表示。例如,正則表達(dá)式 a+? 非貪婪地匹配盡可能少的 "a"。
假設(shè)你有一個(gè)包含多個(gè) HTML 鏈接的文本,例如:
你想提取每個(gè)鏈接的 URL 和鏈接文本。在這種情況下,非貪婪模式非常有用,因?yàn)槊總€(gè)鏈接的 URL 和文本都在一對(duì)標(biāo)簽中。
以下是一個(gè)示例 Java 代碼,演示如何使用非貪婪模式提取鏈接:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用非貪婪模式提取鏈接
* @author: zhangyanfeng
* @create: 2023-11-05 14:25
**/
public class NonGreedyExample {
public static void main(String[] args) {
String htmlText = "Example 1 Example 2";
Pattern pattern = Pattern.compile("(.*?)");
Matcher matcher = pattern.matcher(htmlText);
while (matcher.find()) {
String linkUrl = matcher.group(1);
String linkText = matcher.group(2);
System.out.println("URL: " + linkUrl);
System.out.println("Link Text: " + linkText);
}
}
}
在這個(gè)案例中,我們使用正則表達(dá)式(.*?),其中 (.*?) 表示非貪婪模式。結(jié)果如下:
URL: https://example.com
Link Text: Example 1
URL: https://example2.com
Link Text: Example 2
非貪婪模式(懶惰模式)在正則表達(dá)式中的使用需要根據(jù)具體情況和需求來決定。以下是一些使用非貪婪模式的建議分析:
提取最小單元:非貪婪模式適用于需要提取文本中的最小單元的情況。例如,提取 HTML 標(biāo)簽中的文本、提取鏈接、提取注釋等。它會(huì)盡量匹配最短的文本片段。 避免過度匹配:在某些情況下,貪婪模式可能會(huì)導(dǎo)致過度匹配,匹配整個(gè)文本而不是所需的部分。使用非貪婪模式可以避免這種問題,只匹配所需的最小部分。 性能考慮:非貪婪模式可能需要更多的計(jì)算資源,因?yàn)樗鼤?huì)不斷嘗試匹配更短的文本。在處理大量文本或具有重復(fù)模式的文本時(shí),性能可能受到影響。要注意性能問題。
3.獨(dú)占模式
獨(dú)占模式是一種相對(duì)較新的正則表達(dá)式特性,用 ++ 表示。它會(huì)盡可能多地匹配文本,但不允許回溯。回溯是在匹配失敗后,重新嘗試不同的組合來找到匹配的一部分。獨(dú)占模式不允許回溯,這使得匹配更加高效。例如,正則表達(dá)式 a++ 獨(dú)占地匹配盡可能多的 "a",但不允許回溯。
對(duì)于 Java 正則表達(dá)式來說,它不支持獨(dú)占模式,所以要實(shí)現(xiàn)非回溯的匹配,需要使用非貪婪模式。非貪婪模式可以幫助你實(shí)現(xiàn)不回溯的匹配。我深感抱歉之前的回答有誤。
(三)分組與引用
分組與引用是正則表達(dá)式中的重要概念,它們?cè)试S你在正則表達(dá)式中標(biāo)記、捕獲和引用子表達(dá)式的匹配結(jié)果。
分組是正則表達(dá)式中的一個(gè)重要概念,它允許你將一個(gè)或多個(gè)子表達(dá)式組合在一起,并將它們視為一個(gè)整體。分組有多種用途,包括捕獲子表達(dá)式的匹配結(jié)果、定義重復(fù)次數(shù)、應(yīng)用修飾符等。
1.捕獲分組(Capturing Group)
定義:使用圓括號(hào) () 可以創(chuàng)建捕獲分組。作用:捕獲分組允許你標(biāo)記和捕獲子表達(dá)式的匹配結(jié)果,以便后續(xù)操作使用。被捕獲的內(nèi)容可以在匹配后提取和引用。編號(hào):每個(gè)分組都有一個(gè)編號(hào),從左到右從 1 開始遞增。你可以使用編號(hào)來引用和操作分組中的內(nèi)容。
假設(shè)你有一串文本,其中包含日期,并且日期的格式為 "月/日/年",例如 "12/25/2022"。你想從文本中提取日期,并分別捕獲月、日和年。
(\d{1,2})/(\d{1,2})/(\d{4})
在這個(gè)正則表達(dá)式中,我們使用了三個(gè)捕獲分組,分別捕獲月、日和年。下面是各個(gè)分組的說明:
(\d{1,2}):第一個(gè)捕獲分組,用于捕獲月份。這里 \d{1,2} 匹配一個(gè)或兩個(gè)數(shù)字,表示月份。/:匹配日期中的斜杠分隔符。(\d{1,2}):第二個(gè)捕獲分組,用于捕獲日期(日)。同樣,\d{1,2} 匹配一個(gè)或兩個(gè)數(shù)字。/:再次匹配斜杠分隔符。(\d{4}):第三個(gè)捕獲分組,用于捕獲年份。\d{4} 匹配四個(gè)數(shù)字,表示年份。
在正則表達(dá)式中,捕獲分組用括號(hào) () 創(chuàng)建。每個(gè)捕獲分組都有一個(gè)編號(hào),從左到右從 1 開始遞增。在這個(gè)示例中,我們有三個(gè)捕獲分組,它們分別捕獲了月、日和年。驗(yàn)證如下:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用捕獲分組來提取日期信息
* @author: zhangyanfeng
* @create: 2023-11-05 14:57
**/
public class CapturingGroupExample {
public static void main(String[] args) {
String text = "Today's date is 12/25/2022, and tomorrow is 01/01/2023.";
// 定義匹配日期的正則表達(dá)式模式
String pattern = "(\\d{1,2})/(\\d{1,2})/(\\d{4})";
// 編譯正則表達(dá)式模式
Pattern regex = Pattern.compile(pattern);
// 創(chuàng)建匹配器對(duì)象
Matcher matcher = regex.matcher(text);
// 循環(huán)查找匹配的日期
while (matcher.find()) {
// 使用捕獲分組提取月、日和年
String month = matcher.group(1);
String day = matcher.group(2);
String year = matcher.group(3);
// 打印提取的日期信息
System.out.println("Month: " + month);
System.out.println("Day: " + day);
System.out.println("Year: " + year);
}
}
}
2.非捕獲分組(Non-Capturing Group)
定義:使用 (?:...) 可以創(chuàng)建非捕獲分組。作用:非捕獲分組與捕獲分組類似,但不會(huì)生成捕獲的結(jié)果。它主要用于分組表達(dá)式,而不需要捕獲匹配結(jié)果。語法:(?:pattern),其中 pattern 是子表達(dá)式。
假設(shè)你有一個(gè)文本,其中包含電子郵件地址,你想匹配電子郵件地址,但只對(duì)域名部分感興趣,而不關(guān)心用戶名。你可以使用非捕獲分組來實(shí)現(xiàn)這個(gè)目標(biāo)。
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用非捕獲分組
* @author: zhangyanfeng
* @create: 2023-11-05 15:01
**/
public class NonCapturingGroupExample {
public static void main(String[] args) {
String text = "Contact us at support@example.com or info@company.com";
// 定義匹配電子郵件地址域名的正則表達(dá)式模式
String pattern = "(?<=@)(?:[a-zA-Z0-9.-]+\\.)+[a-zA-Z]{2,4}";
// 編譯正則表達(dá)式模式
Pattern regex = Pattern.compile(pattern);
// 創(chuàng)建匹配器對(duì)象
Matcher matcher = regex.matcher(text);
// 查找匹配的電子郵件地址域名
while (matcher.find()) {
String domainName = matcher.group();
System.out.println("Found domain: " + domainName);
}
}
}
在這個(gè)示例中,我們使用了非捕獲分組"(?<=@)(?:[a-zA-Z0-9.-]+\\.)+[a-zA-Z]{2,4}"來匹配電子郵件地址的域名部分。這個(gè)非捕獲分組用于分組表達(dá)式,但不會(huì)捕獲域名部分的匹配結(jié)果。因此,當(dāng)我們查找匹配的電子郵件地址時(shí),只會(huì)得到完整的電子郵件地址而不包括用戶名。
3.命名捕獲分組(Named Capturing Group)
定義:一些正則表達(dá)式引擎支持命名捕獲分組。它允許為分組指定名稱,以便更容易引用和理解。語法:(?
假設(shè)你有一串文本,其中包含日期,并且日期的格式為 "月/日/年",例如 "12/25/2022"。你想從文本中提取日期,并使用命名捕獲分組分別捕獲月、日和年。
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用命名捕獲分組分別捕獲月、日和年
* @author: zhangyanfeng
* @create: 2023-11-05 15:08
**/
public class NamedCapturingGroupExample {
public static void main(String[] args) {
String text = "Today's date is 12/25/2022, and tomorrow is 01/01/2023.";
// 定義匹配日期的正則表達(dá)式模式,使用命名捕獲分組
String pattern = "(?
// 編譯正則表達(dá)式模式
Pattern regex = Pattern.compile(pattern);
// 創(chuàng)建匹配器對(duì)象
Matcher matcher = regex.matcher(text);
// 查找匹配的日期
while (matcher.find()) {
// 使用命名捕獲分組提取月、日和年
String month = matcher.group("month");
String day = matcher.group("day");
String year = matcher.group("year");
// 打印提取的日期信息
System.out.println("Month: " + month);
System.out.println("Day: " + day);
System.out.println("Year: " + year);
}
}
}
在這個(gè)示例中,我們使用了命名捕獲分組 (?
4. 引用(Backreference)
定義:引用允許你在正則表達(dá)式中引用之前捕獲的內(nèi)容。語法:使用 \n 來引用分組的編號(hào),其中 n 是分組的編號(hào)。作用:引用的主要作用是在正則表達(dá)式中重用相同的文本。它通常用于查找重復(fù)出現(xiàn)的文本或確保兩個(gè)地方的文本匹配相同。
假設(shè)你想匹配連續(xù)出現(xiàn)的相同單詞。例如,你希望找到文本中連續(xù)重復(fù)的單詞,如 "apple apple"、"cat cat cat" 等。
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 找到文本中連續(xù)重復(fù)的單詞
* @author: zhangyanfeng
* @create: 2023-11-05 15:13
**/
public class BackreferenceExample {
public static void main(String[] args) {
String text = "This is an example of repeated words: apple apple, cat cat cat, and dog dog dog dog dog.";
// 定義匹配連續(xù)重復(fù)單詞的正則表達(dá)式模式
String pattern = "\\b(\\w+)(?: \\1)+\\b";
// 編譯正則表達(dá)式模式
Pattern regex = Pattern.compile(pattern);
// 創(chuàng)建匹配器對(duì)象
Matcher matcher = regex.matcher(text);
// 查找匹配的連續(xù)重復(fù)單詞
while (matcher.find()) {
String repeatedWords = matcher.group();
System.out.println("Found repeated words: " + repeatedWords);
}
}
}
在這個(gè)示例中,正則表達(dá)式 \\b(\\w+) \\1\\b 的解釋如下:
\\b 表示單詞邊界,確保只匹配整個(gè)單詞。(\\w+) 是第一個(gè)捕獲分組,匹配一個(gè)或多個(gè)單詞字符。\\1 表示引用第一個(gè)捕獲分組,用來匹配與第一個(gè)捕獲分組相同的文本。
這個(gè)示例會(huì)匹配文本中連續(xù)重復(fù)的單詞,并輸出它們,例如 "apple apple"、"cat cat cat" 和 "dog dog dog dog dog"。
這個(gè)示例會(huì)匹配文本中連續(xù)重復(fù)的單詞,并輸出它們。使用引用可以輕松處理這種情況,而不需要顯式編寫每個(gè)可能的單詞。這在查找重復(fù)文本或特定模式的重復(fù)出現(xiàn)時(shí)非常有用。
5. 重復(fù)分組
你可以使用分組來定義重復(fù)出現(xiàn)的子表達(dá)式。例如,(abc){3} 匹配 "abcabcabc"。
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 重復(fù)分組
* @author: zhangyanfeng
* @create: 2023-11-05 15:19
**/
public class RepeatedGroupExample {
public static void main(String[] args) {
String text = "rfABCDGHabcabcabcJMMMKJBGHJNhgjjhkj";
// 定義匹配重復(fù)的子表達(dá)式的正則表達(dá)式模式
String pattern = "(abc){3}";
// 編譯正則表達(dá)式模式
Pattern regex = Pattern.compile(pattern);
// 創(chuàng)建匹配器對(duì)象
Matcher matcher = regex.matcher(text);
// 查找匹配的文本
while (matcher.find()) {
String matchedText = matcher.group();
System.out.println("Found: " + matchedText);
}
}
}
(四)匹配模式
1.不區(qū)分大小寫
匹配模式中的不區(qū)分大小寫模式允許你創(chuàng)建正則表達(dá)式,它會(huì)匹配文本時(shí)不區(qū)分字符的大小寫。這在需要匹配大小寫不敏感的文本時(shí)非常有用。在正則表達(dá)式中,可以使用 (?i) 開啟不區(qū)分大小寫模式,或使用 (?-i) 關(guān)閉它。
啟用不區(qū)分大小寫模式: 通過在正則表達(dá)式的開頭添加 (?i) 來啟用不區(qū)分大小寫模式。例如,正則表達(dá)式 (?i)apple 將匹配文本中的 "apple"、"Apple"、"aPPle" 等各種大小寫形式。 禁用不區(qū)分大小寫模式: 通過在正則表達(dá)式的開頭添加 (?-i) 來禁用不區(qū)分大小寫模式。在不區(qū)分大小寫模式被禁用后,正則表達(dá)式將嚴(yán)格區(qū)分字符的大小寫。
不區(qū)分大小寫模式對(duì)于需要匹配文本中的標(biāo)識(shí)符、關(guān)鍵字、名稱或其他文本,而不關(guān)心其大小寫形式時(shí)非常有用。例如,如果你要匹配一個(gè)用戶名,用戶可能以不同的大小寫形式輸入,但你希望都能匹配。
以下是一個(gè)示例,演示如何使用不區(qū)分大小寫模式匹配用戶名:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用不區(qū)分大小寫模式匹配用戶名
* @author: zhangyanfeng
* @create: 2023-11-05 15:25
**/
public class CaseInsensitiveExample {
public static void main(String[] args) {
String text = "Welcome, uSer123!";
// 啟用不區(qū)分大小寫模式,匹配用戶名
Pattern pattern = Pattern.compile("(?i)user123");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("Matched: " + matcher.group());
} else {
System.out.println("No match");
}
}
}
在上面的示例中,不區(qū)分大小寫模式允許正則表達(dá)式匹配 "user123",盡管文本中的 "uSer123" 使用不同的大小寫。
不區(qū)分大小寫模式是處理大小寫不敏感匹配需求的有用工具,它可以幫助你更容易地編寫靈活的正則表達(dá)式。
2.點(diǎn)號(hào)通配模式
匹配模式中的點(diǎn)號(hào)通配模式(Dot-All Mode,Single-Line Mode)允許正則表達(dá)式中的點(diǎn)號(hào) . 匹配任何字符,包括換行符。默認(rèn)情況下,點(diǎn)號(hào) . 只匹配除換行符外的字符。點(diǎn)號(hào)通配模式用于需要跨越多行匹配文本的情況。
啟用點(diǎn)號(hào)通配模式: 通過在正則表達(dá)式的開頭添加 (?s) 來啟用點(diǎn)號(hào)通配模式。點(diǎn)號(hào)通配模式使正則表達(dá)式中的點(diǎn)號(hào) . 能夠匹配包括換行符在內(nèi)的任何字符。 禁用點(diǎn)號(hào)通配模式: 通過在正則表達(dá)式的開頭添加 (?-s) 來禁用點(diǎn)號(hào)通配模式。在禁用點(diǎn)號(hào)通配模式后,點(diǎn)號(hào) . 將只匹配除換行符外的字符,與默認(rèn)行為相同。
點(diǎn)號(hào)通配模式通常用于處理包含多行文本的情況,例如處理包含換行符的段落、HTML 標(biāo)簽、或需要匹配多行注釋的文本。
以下是一個(gè)示例,演示如何使用點(diǎn)號(hào)通配模式匹配跨越多行的 HTML 標(biāo)簽內(nèi)容:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用點(diǎn)號(hào)通配模式匹配跨越多行的 HTML 標(biāo)簽內(nèi)容
* @author: zhangyanfeng
* @create: 2023-11-05 15:30
**/
public class DotAllModeExample {
public static void main(String[] args) {
String html = "
// 啟用點(diǎn)號(hào)通配模式,匹配 div 標(biāo)簽內(nèi)容
Pattern pattern = Pattern.compile("
Matcher matcher = pattern.matcher(html);
if (matcher.find()) {
String divContent = matcher.group(1);
System.out.println("Div content: " + divContent);
} else {
System.out.println("No match");
}
}
}
在上面的示例中,點(diǎn)號(hào)通配模式允許正則表達(dá)式匹配包括換行符在內(nèi)的多行 HTML
實(shí)際上,Java 中可以通過兩種方式來啟用點(diǎn)號(hào)通配模式:
使用 (?s):直接在正則表達(dá)式中的開頭添加 (?s),如下所示:
Pattern pattern = Pattern.compile("(?s)
使用 Pattern.DOTALL 標(biāo)志:在編譯正則表達(dá)式時(shí),通過傳遞 Pattern.DOTALL 標(biāo)志來啟用點(diǎn)號(hào)通配模式,如下所示:
Pattern pattern = Pattern.compile("
兩種方法都可以實(shí)現(xiàn)點(diǎn)號(hào)通配模式。在前一個(gè)示例中,我使用了第二種方法,使用 Pattern.DOTALL 標(biāo)志,以演示點(diǎn)號(hào)通配模式的應(yīng)用。如果你更喜歡在正則表達(dá)式中直接添加 (?s),你可以按照第一種方法來使用它。
點(diǎn)號(hào)通配模式在處理需要跨越多行的文本匹配時(shí)非常有用,它使點(diǎn)號(hào) . 具有更廣泛的匹配能力。
3.多行模式
多行模式是一種正則表達(dá)式匹配模式,它主要影響 ^ 和 $ 這兩個(gè)錨點(diǎn)的匹配行為。默認(rèn)情況下,^ 匹配字符串的開頭,而 $ 匹配字符串的結(jié)尾。啟用多行模式后,這些錨點(diǎn)將匹配文本的每一行的開頭和結(jié)尾。
啟用多行模式: 通過在正則表達(dá)式的開頭添加 (?m) 來啟用多行模式。多行模式使正則表達(dá)式中的 ^ 和 $ 錨點(diǎn)匹配每行文本的開頭和結(jié)尾。 禁用多行模式: 如果不需要多行匹配模式,可以在正則表達(dá)式的開頭添加 (?-m) 來禁用它。在禁用多行模式后,^ 和 $ 仍然只匹配整個(gè)字符串的開頭和結(jié)尾。
多行模式通常用于處理包含多行文本的情況,例如處理文本文件中的多行注釋、日志文件或需要逐行處理的文本數(shù)據(jù)。
以下是一個(gè)示例,演示如何使用多行模式匹配包含多行注釋的文本:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用多行模式匹配包含多行注釋的文本
* @author: zhangyanfeng
* @create: 2023-11-05 15:37
**/
public class MultilineModeExample {
public static void main(String[] args) {
String text = "This is a sample text.\n" +
"/* This is a multiline\n" +
" comment. */\n" +
"More text.";
// 啟用多行模式,匹配多行注釋內(nèi)容
Pattern pattern = Pattern.compile("/\\*.*?\\*/", Pattern.MULTILINE | Pattern.DOTALL);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
String comment = matcher.group();
System.out.println("Multiline Comment: " + comment);
}
}
}
在上面的示例中,多行模式使正則表達(dá)式匹配多行注釋內(nèi)容,而不僅僅匹配整個(gè)文本的開頭和結(jié)尾。多行模式是一種有用的匹配模式,它允許你更精確地處理多行文本。
4.注釋模式
匹配模式中的注釋模式(Comments Mode)允許你在正則表達(dá)式中添加注釋,以提高正則表達(dá)式的可讀性和維護(hù)性。注釋模式允許你在正則表達(dá)式中添加注釋以解釋模式的目的和行為,而這些注釋不會(huì)影響匹配的結(jié)果。
啟用注釋模式: 在正則表達(dá)式中使用 (?x) 或 (?# ... ) 來啟用注釋模式。(?x) 告訴正則表達(dá)式引擎要忽略空白字符(除了在字符類內(nèi)部),并且允許添加注釋。你可以使用 (?# ... ) 添加注釋,其中 ... 是你希望添加的注釋內(nèi)容。 注釋內(nèi)容: 在 (?# ... ) 中的注釋內(nèi)容可以是任何描述性文本,用于解釋正則表達(dá)式的目的、匹配模式或任何你認(rèn)為有助于理解和維護(hù)正則表達(dá)式的信息。注釋內(nèi)容不會(huì)影響匹配結(jié)果,它們僅用于文檔和可讀性。
注釋模式通常用于復(fù)雜的正則表達(dá)式,以幫助其他人或你自己更容易地理解和維護(hù)正則表達(dá)式。注釋模式使正則表達(dá)式更易于閱讀,特別是在包含多個(gè)子表達(dá)式和匹配模式的情況下。
以下是一個(gè)示例,演示如何使用注釋模式添加注釋來解釋正則表達(dá)式的含義:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用注釋模式添加注釋來解釋正則表達(dá)式的含義
* @author: zhangyanfeng
* @create: 2023-11-05 15:41
**/
public class CommentsModeExample {
public static void main(String[] args) {
String text = "Hello, John! My name is ZYF";
// 啟用注釋模式,匹配問候語
Pattern pattern = Pattern.compile(
"(?x) # 啟用注釋模式\n" +
"Hello, # 匹配 Hello\n" +
"\\s # 匹配一個(gè)空白字符\n" +
"John # 匹配 John"
);
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("Matched: " + matcher.group());
} else {
System.out.println("No match");
}
}
}
在上面的示例中,注釋模式通過 (?x) 啟用,允許在正則表達(dá)式中添加注釋,以更清晰地解釋模式的目的。注釋模式是一種有用的工具,它提高了正則表達(dá)式的可讀性和維護(hù)性,特別是在編寫復(fù)雜的正則表達(dá)式時(shí)。
(五)斷言(Assertion)
正則表達(dá)式中的斷言(Assertion)是一種特殊的匹配條件,它允許你指定匹配目標(biāo)的位置而不是實(shí)際字符。最常見的斷言有三種:?jiǎn)卧~的邊界斷言、行的開始或結(jié)束斷言,以及環(huán)視斷言。斷言是非常有用的工具,它允許你精確控制匹配的位置和條件,以滿足特定的匹配需求。不同類型的斷言可以用于不同的情況,使正則表達(dá)式更強(qiáng)大和靈活。
1.單詞的邊界
單詞的邊界斷言是正則表達(dá)式中的一種斷言,用于匹配單詞的開始或結(jié)束位置,而不是整個(gè)單詞。它通常使用特殊字符 \b 表示單詞的邊界,或使用 \B 表示非單詞的邊界。
\b: \b 是單詞的邊界斷言,它匹配單詞的開始或結(jié)束位置。單詞被定義為由字母、數(shù)字和下劃線組成的字符序列。這意味著 \b 匹配單詞的起始和結(jié)束,以及單詞之間的位置。例如,正則表達(dá)式 \bword\b 匹配整個(gè)單詞 "word",但不匹配 "sword" 或 "words" 中的 "word"。 \B: \B 是非單詞的邊界斷言,它匹配不是單詞的起始或結(jié)束位置。換句話說,它匹配單詞內(nèi)部的位置,或者非單詞字符的位置。例如,正則表達(dá)式 \Bword\B 匹配 "sword" 或 "words" 中的 "word",但不匹配整個(gè)單詞 "word"。
單詞的邊界斷言通常用于需要精確匹配整個(gè)單詞的情況,而不是部分匹配。它在文本處理中常用于查找特定單詞或標(biāo)識(shí)符。以下是一些示例用法:
匹配一個(gè)特定單詞(例如,\bapple\b 匹配整個(gè)單詞 "apple")。查找文本中的標(biāo)識(shí)符或關(guān)鍵字(例如,\bif\b 匹配單詞 "if" 作為關(guān)鍵字)。分隔文本為單詞或標(biāo)識(shí)符(使用 \b\w+\b 可以提取文本中的所有單詞或標(biāo)識(shí)符)。
單詞的邊界斷言是正則表達(dá)式中非常有用和常見的工具,用于精確匹配文本中的單詞或標(biāo)識(shí)符。
在Java中使用單詞邊界斷言來驗(yàn)證和匹配文本:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用單詞邊界斷言來驗(yàn)證和匹配文本
* @author: zhangyanfeng
* @create: 2023-11-05 16:16
**/
public class WordBoundaryExample {
public static void main(String[] args) {
// 文本示例
String text = "The quick brown fox jumps over the lazy dog.";
// 使用\b斷言匹配整個(gè)單詞 "fox"
Pattern pattern1 = Pattern.compile("\\bfox\\b");
Matcher matcher1 = pattern1.matcher(text);
while (matcher1.find()) {
System.out.println("Match: " + matcher1.group());
}
// 使用\B斷言匹配非單詞邊界的 "fox"
Pattern pattern2 = Pattern.compile("\\Bfox\\B");
Matcher matcher2 = pattern2.matcher(text);
while (matcher2.find()) {
System.out.println("Non-Match: " + matcher2.group());
}
}
}
2.行的開始或結(jié)束
斷言是正則表達(dá)式中的一種特殊元字符,用于指定匹配的位置而不匹配實(shí)際字符。行的開始和行的結(jié)束斷言用于匹配文本的開頭和結(jié)尾。以下是關(guān)于行的開始和行的結(jié)束斷言的詳細(xì)介紹:
行的開始斷言 ^:
^ 是行的開始斷言,用于匹配文本的開頭。例如,正則表達(dá)式 ^apple 匹配以 "apple" 開頭的文本。示例:^apple 匹配 "apple pie" 中的 "apple",但不匹配 "pineapple"。
行的結(jié)束斷言 $:
$ 是行的結(jié)束斷言,用于匹配文本的結(jié)尾。例如,正則表達(dá)式 apple$ 匹配以 "apple" 結(jié)尾的文本。示例:apple$ 匹配 "caramel apple" 中的 "apple",但不匹配 "apple pie"。
這些行的開始和行的結(jié)束斷言非常有用,因?yàn)樗鼈冊(cè)试S精確地控制匹配的位置。它們通常用于查找或驗(yàn)證文本的起始或終止部分,例如查找文件中以特定字符串開頭或結(jié)尾的行。
下面是一個(gè)示例,演示如何在Java中使用行的開始和行的結(jié)束斷言:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用行的開始和行的結(jié)束斷言
* @author: zhangyanfeng
* @create: 2023-11-05 16:28
**/
public class LineBoundaryExample {
public static void main(String[] args) {
// 文本示例
String text = "apple\nbanana\ncherry\norange";
// 使用^斷言匹配行的開始
Pattern pattern1 = Pattern.compile("^apple", Pattern.MULTILINE);
Matcher matcher1 = pattern1.matcher(text);
while (matcher1.find()) {
System.out.println("Match at line start: " + matcher1.group());
}
// 使用$斷言匹配行的結(jié)束
Pattern pattern2 = Pattern.compile("cherry$", Pattern.MULTILINE);
Matcher matcher2 = pattern2.matcher(text);
while (matcher2.find()) {
System.out.println("Match at line end: " + matcher2.group());
}
}
}
在這個(gè)示例中,我們使用 ^ 斷言來匹配以 "apple" 開頭的行,并使用 $ 斷言來匹配以 "cherry" 結(jié)尾的行。運(yùn)行代碼,你將看到以下輸出:
Match at line start: apple
Match at line end: cherry
這表明成功匹配了行的開頭和行的結(jié)尾??梢愿鶕?jù)需要修改正則表達(dá)式模式以匹配不同的文本部分。
3.環(huán)視(Lookaround)
環(huán)視(Lookaround)是正則表達(dá)式中的一種高級(jí)特性,用于在匹配時(shí)查看前面或后面是否滿足某種條件,但實(shí)際上不匹配這些條件。環(huán)視分為正向環(huán)視和負(fù)向環(huán)視,用于查看某些條件是否存在或不存在。
正向環(huán)視(Positive Lookaround):正向環(huán)視用于查看前面或后面是否滿足某種條件,并且只有在滿足條件時(shí)才匹配成功。正向環(huán)視分為正向預(yù)查(Positive Lookahead)和正向回顧(Positive Lookbehind)兩種情況。
正向預(yù)查(Positive Lookahead):正向預(yù)查由 (?= ...) 表示,其中 ... 是要查看的條件。它要求緊跟在這個(gè)條件后面的內(nèi)容匹配成功。 正向回顧(Positive Lookbehind):正向回顧由 (?<= ...) 表示,其中 ... 是要查看的條件。它要求緊跟在這個(gè)條件前面的內(nèi)容匹配成功。
負(fù)向環(huán)視(Negative Lookaround):負(fù)向環(huán)視用于查看前面或后面是否不滿足某種條件,并且只有在不滿足條件時(shí)才匹配成功。負(fù)向環(huán)視分為負(fù)向預(yù)查(Negative Lookahead)和負(fù)向回顧(Negative Lookbehind)兩種情況。
負(fù)向預(yù)查(Negative Lookahead):負(fù)向預(yù)查由 (?! ...) 表示,其中 ... 是要查看的條件。它要求緊跟在這個(gè)條件后面的內(nèi)容不匹配成功。 負(fù)向回顧(Negative Lookbehind):負(fù)向回顧由 (?
環(huán)視的主要作用是在匹配時(shí)查看前面或后面的文本內(nèi)容,以便更精確地定位需要的模式。這對(duì)于復(fù)雜的匹配和替換操作非常有用。
以下是一個(gè) Java 代碼示例,演示如何在正則表達(dá)式中使用環(huán)視(Lookaround)來驗(yàn)證文本中的條件:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 使用環(huán)視(Lookaround)來驗(yàn)證文本中的條件
* @author: zhangyanfeng
* @create: 2023-11-05 16:38
**/
public class LookaroundExample {
public static void main(String[] args) {
// 文本示例
String text = "The quick brown fox jumps over the lazy dog.";
// 正向預(yù)查示例:匹配包含 "fox" 后面是 "jumps" 的情況
Pattern pattern1 = Pattern.compile("fox(?= jumps)");
Matcher matcher1 = pattern1.matcher(text);
while (matcher1.find()) {
System.out.println("Positive Lookahead: " + matcher1.group());
}
// 負(fù)向預(yù)查示例:匹配包含 "fox" 后面不是 "lazy" 的情況
Pattern pattern2 = Pattern.compile("fox(?! lazy)");
Matcher matcher2 = pattern2.matcher(text);
while (matcher2.find()) {
System.out.println("Negative Lookahead: " + matcher2.group());
}
// 正向回顧示例:匹配包含 "fox" 前面是 "quick" 的情況
text = "The quick fox jumps over the lazy dog.";
Pattern pattern3 = Pattern.compile("(?<=quick )fox");
Matcher matcher3 = pattern3.matcher(text);
while (matcher3.find()) {
System.out.println("Positive Lookbehind: " + matcher3.group());
}
// 負(fù)向回顧示例:匹配包含 "fox" 前面不是 "brown" 的情況
Pattern pattern4 = Pattern.compile("(?
Matcher matcher4 = pattern4.matcher(text);
while (matcher4.find()) {
System.out.println("Negative Lookbehind: " + matcher4.group());
}
}
}
這個(gè)示例展示了正向預(yù)查、負(fù)向預(yù)查、正向回顧和負(fù)向回顧的使用。
(六)正則轉(zhuǎn)義
正則表達(dá)式中的轉(zhuǎn)義用于指示正則表達(dá)式引擎將某些字符解釋為特殊字符而不是普通字符。正則表達(dá)式中的特殊字符通常用于表示匹配規(guī)則和模式。以下是一些常見的正則表達(dá)式中需要轉(zhuǎn)義的特殊字符:
\: 反斜杠(\)用于轉(zhuǎn)義緊跟其后的字符,使其變成普通字符。例如,\. 表示匹配點(diǎn)號(hào)而不是匹配任何字符。 ^: 插入符(^)通常用于表示匹配行的開頭,但在字符類(方括號(hào)內(nèi))中,它表示反義。要匹配插入符字符本身,需要使用 \^。 $: 美元符號(hào)($)通常用于表示匹配行的結(jié)尾。要匹配美元符號(hào)字符本身,需要使用 \$。 .: 點(diǎn)號(hào)(.)通常用于表示匹配除換行符之外的任何字符。要匹配點(diǎn)號(hào)字符本身,需要使用 \.。 *, +, ?, {, }: 這些字符通常用于表示量詞,指定前面的字符可以重復(fù)多少次。要匹配這些字符本身,需要使用 \*, \+, \?, \{, \}。 |: 豎線(|)通常用于表示或操作,匹配兩個(gè)選項(xiàng)中的一個(gè)。要匹配豎線字符本身,需要使用 \|。 (): 圓括號(hào)通常用于分組表達(dá)式。要匹配圓括號(hào)字符本身,需要使用 \(\)。 []: 方括號(hào)通常用于定義字符類,匹配其中的任何字符。要匹配方括號(hào)字符本身,需要使用 \[\]。 \: 反斜杠本身需要進(jìn)行轉(zhuǎn)義,因此要匹配反斜杠字符本身,需要使用 \\。
要使用這些特殊字符作為普通字符進(jìn)行匹配,只需在它們前面添加反斜杠進(jìn)行轉(zhuǎn)義。這樣正則表達(dá)式引擎會(huì)將它們視為普通字符而不是特殊字符。
以下是一個(gè)Java類,用于驗(yàn)證正則表達(dá)式中的轉(zhuǎn)義字符:
package org.zyf.javabasic.regex;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @program: zyfboot-javabasic
* @description: 驗(yàn)證正則表達(dá)式中的轉(zhuǎn)義字符
* @author: zhangyanfeng
* @create: 2023-11-05 16:48
**/
public class RegexEscapeExample {
public static void main(String[] args) {
// 要匹配的文本
String text = "This is a dot (.) and a question mark (?).";
// 使用正則表達(dá)式匹配點(diǎn)號(hào)和問號(hào),需要轉(zhuǎn)義這兩個(gè)字符
String regex = "\\.";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
System.out.println("Matching dots:");
while (matcher.find()) {
System.out.println("Match: " + matcher.group());
}
// 使用正則表達(dá)式匹配問號(hào)
regex = "\\?";
pattern = Pattern.compile(regex);
matcher = pattern.matcher(text);
System.out.println("\nMatching question marks:");
while (matcher.find()) {
System.out.println("Match: " + matcher.group());
}
}
}
在這個(gè)示例中,我們創(chuàng)建了一個(gè)Java類 RegexEscapeExample,并使用正則表達(dá)式來匹配文本中的點(diǎn)號(hào)和問號(hào)。由于點(diǎn)號(hào)和問號(hào)在正則表達(dá)式中是特殊字符,所以需要使用反斜杠進(jìn)行轉(zhuǎn)義,即 \\. 和 \\?。
柚子快報(bào)激活碼778899分享:認(rèn)真來看下正則表達(dá)式
文章來源
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。