Java中,可以使用正則表達式來提取HTML中的任意內容。以下是一個示例代碼,演示如何使用正則表達式從HTML中提取文本:
import java.util.regex.Matcher; import java.util.regex.Pattern; public class HtmlParser { public static void main(String[] args) { String html = "<html><head><title>My Website</title></head><body><p>This is some sample text.</p></body></html>"; Pattern pattern = Pattern.compile("<p[^>]*>(.*?)</p>"); Matcher matcher = pattern.matcher(html); String pText = matcher.group(1); System.out.println(pText); } }
在上面的代碼中,我們首先定義了一個HTML字符串,然后使用Pattern和Matcher類來匹配HTML中的文本。Pattern類用于定義正則表達式,Matcher類用于在HTML中查找匹配的文本。
在正則表達式中,我們使用了<p[^>]*>來匹配以<p>開頭,后面跟著任意數量的字符,再以</p>結尾的文本。其中,[^>]*表示匹配任意數量的字符,</p>表示匹配</p>后面的任意字符。
最后,我們使用group(1)方法來獲取匹配的文本,并將其打印到控制臺上。
需要注意的是,正則表達式可以根據HTML標簽的不同來進行不同的
正則表達式(Regular Expression),又稱正規表示法,常簡稱為正則表達式、正則式或規則(Reading),其實是一種字符串匹配的工具,它可以用來描述字符序列的模式。
在 Java 中,正則表達式主要用于以下兩個方面:
正則表達式由兩種基本字符類型組成:
原子指單個的、不可再分的匹配單元,原子表達式就是由原子組成的正則表達式。常見的原子有:
元字符是正則表達式中最為重要和常用的部分,用于匹配單個字符或一組字符。其中常見的元字符如下:
(1)基本元字符
對應單個字符。
(2)量詞元字符
用于描述字符的數量。
注意:使用*和+ 時,表達式會盡可能地去匹配所有符合條件的字符串。因此,可能會導致效率低下和執行時間過長的問題。如果確定匹配的字符串不會太長,可以使用貪婪模式(Greedy)來提高正則表達式的性能。例如,a._b 會匹配從a開始到b結束之間的所有內容,包括中間的換行符等;而a._?b 只會匹配第一個a 和第一個b之間的部分。
(3)分組元字符
用于將表達式中若干個子項組成一個整體。常用的分組元字符有:
(4)限定符
用于限制某個元字符在正則表達式中出現的次數。常見的限定符有:
字符 | 匹配 | 示例 |
. | 任意單個字符,除換行符外 | jav.匹配java |
[ ] | [ ] 中的任意一個字符 | java匹配j[abc]va |
- | [ ] 內表示字符范圍 | java匹配[a-z]av[a-g] |
^ | 在[ ]內的開頭,匹配除[ ]內的字符之外的任意一個字符 | java匹配jb-fva |
| | 或 | x|y匹配x或y |
|將下一字符標記為特殊字符、文本、反向引用或八進制轉義符 | (匹配( | |
$ | 匹配輸入字符串結尾的位置。如果設置了 RegExp 對象的 Multiline 屬性,$ 還會與"\n"或"\r"之前的位置匹配。 | ;$匹配位于一行及外圍的;號 |
* | 零次或多次匹配前面的字符 | zo*匹配zoo或z |
+ | 一次或多次匹配前面的字符 | zo+匹配zo或zoo |
? | 零次或一次匹配前面的字符 | zo?匹配z或zo |
p{n} | n 是非負整數。正好匹配 n 次 | o{2}匹配food中的兩個o |
p{n,} | n 是非負整數。至少匹配 n 次 | o{2}匹配foood中的所有o |
p{n,m} | M 和 n 是非負整數,其中 n <= m。匹配至少 n 次,至多 m 次 | o{1,3}匹配fooood中的三個o |
\p{P} | 一個標點字符 !"#$%&'()*+,-./:;<=>?@[]^_'{|}~ | J\p{P}a匹配J?a |
\b | 匹配一個字邊界 | va\b匹配java中的va,但不匹配javar中的va |
\B | 非字邊界匹配 | va\B匹配javar中的va,但不匹配java中的va |
\d | 數字字符匹配 | 1[\d]匹配13 |
\D | 非數字字符匹配 | [\D]java匹配Jjava |
\w | 單詞字符 | java匹配[\w]ava |
\W | 非單詞字符 | $java匹配[\W]java |
\s | 空白字符 | Java 2匹配Java\s2 |
\S | 非空白字符 | java匹配 j[\S]va |
\f | 匹配換頁符 | 等效于\x0c和\cL |
\n | 匹配換行符 | 等效于\x0a和\cJ |
Matcher 類是一個抽象類,可以通過調用 Pattern 類的 matcher() 方法來獲取 Matcher 對象。
常用方法如下:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherDemo {
public static void main(String[] args) {
String str = "This is a test string";
// 創建 Pattern 對象
Pattern pattern = Pattern.compile("\\w+");
// 創建 Matcher 對象
Matcher matcher = pattern.matcher(str);
int count = 0;
while (matcher.find()) {
System.out.println("Match " + (++count) + ": " + matcher.group());
System.out.println("Starting index: " + matcher.start());
System.out.println("Ending index: " + matcher.end());
}
}
}
上面的代碼使用 Pattern 類和 Matcher 類來對字符串進行匹配,輸出結果如下:
Match 1: This
Starting index: 0
Ending index: 4
Match 2: is
Starting index: 5
Ending index: 7
Match 3: a
Starting index: 8
Ending index: 8
Match 4: test
Starting index: 10
Ending index: 13
Match 5: string
Starting index: 15
Ending index: 20
Pattern 類提供了一些常見的正則表達式。
常用方法如下:
代碼示例:
import java.util.Arrays;
import java.util.regex.Pattern;
public class PatternDemo {
public static void main(String[] args) {
String str = "1,2;3,4,5";
// 使用逗號或分號分割字符串
Pattern pattern = Pattern.compile("[,;]");
String[] parts = pattern.split(str);
System.out.println(Arrays.toString(parts));
// 將數字替換為 X
String result = pattern.matcher(str).replaceAll("X");
System.out.println(result);
}
}
上面的代碼使用 Pattern 類的 split() 和 replaceAll() 方法來對字符串進行操作,輸出結果如下:
[1, 2, 3, 4, 5]
X X X X X
(1)public static Pattern compile(String regex)
說明:Pattern類的一個靜態方法,用于將給定的正則表達式字符串編譯為一個Pattern對象。這個方法通常用于將一個常見的正則表達式字符串編譯成一個Pattern對象,以便后續的重復使用
Pattern pattern = Pattern.compile("a*b");
(2)public static Pattern compile(String regex, int flags)
說明:Pattern.compile(String regex, int flags)是Pattern類的一個靜態方法,用于根據給定的正則表達式字符串和標志位來編譯成一個Pattern對象。這個方法允許你在編譯正則表達式時指定一些標志,以控制匹配的行為。
參數regex是要編譯的正則表達式字符串,flags是一個整數,表示匹配的標志位。常用的標志位包括:
使用這個重載的compile方法,可以更靈活地控制正則表達式的匹配行為。
//正則表達式"a*b"編譯成一個Pattern對象,并指定了忽略大小寫和多行模式的標志位。這樣就可以在后續的匹配操作中,按照指定的標志位規則進行匹配
Pattern pattern = Pattern.compile("a*b", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
(3)public static boolean matches(String regex, CharSequence input)
說明:Pattern.matches(String regex, CharSequence input) 是Pattern類的一個靜態方法,用于判斷給定的輸入字符串是否完全匹配指定的正則表達式。
參數regex是要用來進行匹配的正則表達式字符串,參數 input 是要進行匹配的輸入字符序列。
這個方法會嘗試將整個輸入序列與正則表達式進行匹配,如果整個輸入字符串與正則表達式完全匹配,則返回 true;否則返回false。
boolean isMatch = Pattern.matches("a*b", "aaaab");
//運行結果: isMatch = true
//上面的代碼將會用正則表達式 "ab" 對字符串 "aaaab" 進行匹配,因為 "aaaab" 符合 "a" 的模式,所以 isMatch 會被賦值為 true
(4)public static String quote(String s)
說明:Pattern.quote(String s) 是 Pattern 類的一個靜態方法,用于返回指定字符串的字面量模式字符串。這個方法可以將輸入的字符串轉換為字面量模式,以便在正則表達式中進行精確匹配。于正則表達式中可能包含特殊字符,如果需要在正則表達式中精確匹配一個字符串,就需要對字符串進行轉義處理,這時可以使用quote方法來實現。
//我們希望匹配字符串 "(.)",但是這個字符串包含了正則表達式中的特殊字符 "()" 和 ".",為了確保在正則表達式中能夠精確匹配這個字符串,我們可以使用 quote 方法來轉義這個字符串,得到的 regex 就是 \(\.\*\),它可以在正則表達式中精確匹配原始的字符串 "(.*)"。
String input = "(.*)";
String regex = Pattern.quote(input);
(5)public String pattern()
說明:pattern() 方法是在 Pattern 類中的一個公共方法,它返回該正則表達式對象所表示的模式,你可以使用這個 Pattern 對象調用 pattern() 方法,以獲取該正則表達式的字符串表示形式。
String regex = "ab+c";
Pattern pattern = Pattern.compile(regex);
String patternString = pattern.pattern();
System.out.println(patternString); // 輸出:"ab+c"
(6)public Matcher matcher(CharSequence input)
說明:matcher(CharSequence input) 方法是在Pattern 類中的一個公共方法,它用于創建一個匹配器對象,并將指定的輸入序列與正則表達式進行匹配。
在 Java 中,可以使用Pattern類的 matcher(CharSequence input) 方法來創建一個 Matcher 對象,該對象可以用于執行匹配操作。CharSequence 表示一個字符序列,可以是字符串或其他類型的字符序列。
String regex = "\\d+";
String input = "12345";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
boolean isMatch = matcher.matches();
System.out.println(isMatch); // 輸出:true
我們首先定義了一個正則表達式字符串\d+,表示匹配一個或多個數字。然后,我們定義了一個輸入字符串 input,其值為"12345"。
接下來,我們使用Pattern.compile()方法編譯正則表達式,并將返回的 Pattern 對象賦值給 pattern 變量。然后,我們使用pattern.matcher(input)方法創建一個Matcher對象,該對象用于對輸入序列進行匹配。
最后,我們調用matcher.matches()方法來檢查輸入序列是否完全匹配正則表達式。如果匹配成功,則返回 true,否則返回false。在上述示例中,由于輸入字符串"12345"完全匹配正則表達式 \d+,所以輸出結果為true。
因此,matcher(CharSequence input) 方法的作用是創建一個匹配器對象,并將指定的輸入序列與正則表達式進行匹配。
(7)public Predicate<String> asPredicate()
說明:asPredicate() 方法是在 Pattern 類中的一個公共方法,它返回一個 Predicate<String> 對象,用于將正則表達式作為謂詞進行匹配。
在 Java 中,Predicate 是一個函數接口,它接受一個輸入參數并返回一個布爾值結果。Predicate<String> 表示該謂詞接受一個字符串類型的輸入參數。
String regex = "\\d+";
Pattern pattern = Pattern.compile(regex);
Predicate<String> predicate = pattern.asPredicate();
System.out.println(predicate.test("123")); // 輸出:true
System.out.println(predicate.test("abc")); // 輸出:false
我們首先定義了一個正則表達式字符串\d+,表示匹配一個或多個數字。然后,我們使用 Pattern.compile() 方法編譯正則表達式,并將返回的Pattern對象賦給pattern變量。
接下來,我們調用pattern.asPredicate()方法,將正則表達式轉換為一個Predicate<String>對象,并將其賦值給 predicate 變量。
最后,我們可以使用predicate.test(String input)方法來測試輸入字符串是否與正則表達式匹配。如果匹配成功,則返回true,否則返回false。在上述示例中,由于輸入字符串"123"符合正則表達式\d+的模式,所以第一次輸出結果為true;而輸入字符串"abc"不符合該模式,所以第二次輸出結果為false。
因此,asPredicate() 方法的作用是將正則表達式轉換為一個Predicate<String>對象,用于對輸入字符串進行匹配。
(8)public int flags()
說明:flags() 方法是在 Pattern 類中的一個公共方法,用于返回當前正則表達式模式的標志位(flags)。
在 Java 中,Pattern 類的正則表達式模式可以使用一些標志來修改其行為。這些標志可以通過在正則表達式字符串中添加特殊的標記來指定。
以下是一些常用的標志:
flags() 方法將返回一個整數值,表示當前正則表達式模式的標志位。該整數值是由上述標志的按位或組合而成。
String regex = "abc";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
int flags = pattern.flags();
System.out.println(flags); // 輸出:2
我們首先定義了一個正則表達式字符串 "abc",然后使用 Pattern.compile() 方法編譯該正則表達式,并將 Pattern.CASE_INSENSITIVE | Pattern.MULTILINE 作為第二個參數傳遞給方法,這樣我們同時啟用了 CASE_INSENSITIVE 和 MULTILINE 兩個標志。
接下來,我們調用 pattern.flags() 方法,返回一個整數值,表示當前正則表達式模式的標志位。
最后,我們打印出 flags 的值,它將輸出 2,表示 CASE_INSENSITIVE 和 MULTILINE 兩個標志被啟用。
因此,flags() 方法的作用是返回當前正則表達式模式的標志位的整數值。
**(9)public String[] split(CharSequence input)**
說明:split(CharSequence input) 方法是在 Pattern 類中的一個公共方法,用于將輸入序列根據正則表達式進行拆分,并返回拆分后的字符串數組
在 Java 中,可以使用 Pattern 類的 split(CharSequence input) 方法來將一個字符序列按照正則表達式進行拆分。CharSequence 表示一個字符序列,可以是字符串或其他類型的字符序列。
String regex = "\\s+";
String input = "Hello World Java";
Pattern pattern = Pattern.compile(regex);
String[] parts = pattern.split(input);
for (String part : parts) {
System.out.println(part);
}
/*
運行結果:
Hello
World
Java
*/
我們首先定義了一個正則表達式字符串\s+,表示匹配一個或多個空格。然后,我們定義了一個輸入字符串 input,其值為 "Hello World Java",包含多個連續空格。
接下來,我們使用 Pattern.compile() 方法編譯正則表達式,并將返回的 Pattern 對象賦給 pattern 變量。然后,我們調用 pattern.split(input) 方法,將輸入字符串按照正則表達式進行拆分。拆分后的結果將存儲在一個字符串數組 parts 中。
最后,我們使用一個循環遍歷輸出 parts 數組中的每個元素,以顯示拆分后的結果
(10)public String[] split(CharSequence input, int limit)
說明:可以使用 Pattern 類的 split(CharSequence input, int limit) 方法來將一個字符序列按照正則表達式進行拆分,并限制拆分的數量。CharSequence 表示一個字符序列,可以是字符串或其他類型的字符序列,而 limit 參數表示拆分的最大數量
String regex = "\\s+";
String input = "Hello World Java";
Pattern pattern = Pattern.compile(regex);
String[] parts = pattern.split(input, 2);
for (String part : parts) {
System.out.println(part);
}
/*
運行結果:
Hello
World Java
*/
我們首先定義了一個正則表達式字符串 \s+,表示匹配一個或多個空格。然后,我們定義了一個輸入字符串 input,其值為 "Hello World Java",包含多個連續空格。
接下來,我們使用 Pattern.compile() 方法編譯正則表達式,并將返回的 Pattern 對象賦給 pattern 變量。然后,我們調用 pattern.split(input, 2) 方法,將輸入字符串按照正則表達式進行拆分,并限制拆分的最大數量為 2。拆分后的結果將存儲在一個字符串數組 parts 中。
最后,我們使用一個循環遍歷輸出 parts 數組中的每個元素,以顯示拆分后的結果。
(11)public String[] split(CharSequence input, int limit)
說明:splitAsStream(final CharSequence input) 方法是在 Pattern 類中的一個公共方法,用于將輸入序列根據正則表達式進行拆分,并返回一個 Stream<String> 流,在流中包含了拆分后的字符串元素。
可以使用 Pattern 類的 splitAsStream(final CharSequence input) 方法來將一個字符序列按照正則表達式進行拆分,并生成一個流對象,該流中包含了拆分后的字符串元素。
import java.util.regex.Pattern;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
String regex = "\\s+";
String input = "Hello World Java";
Pattern pattern = Pattern.compile(regex);
Stream<String> stream = pattern.splitAsStream(input);
stream.forEach(System.out::println);
}
}
/*
運行結果:
Hello
World
Java
*/
我們首先定義了一個正則表達式字符串\s+,表示匹配一個或多個空格。然后,我們定義了一個輸入字符串 input,其值為 "Hello World Java",包含多個連續空格。
接下來,我們使用 Pattern.compile() 方法編譯正則表達式,并將返回的 Pattern 對象賦給 pattern 變量。然后,我們調用 pattern.splitAsStream(input) 方法,將輸入字符串按照正則表達式進行拆分,并生成一個Stream<String> 流對象,其中包含了拆分后的字符串元素。
最后,我們使用 forEach() 方法遍歷流中的每個字符串元素,并打印輸出。
(12)public static String quoteReplacement(String s)
說明:quoteReplacement(String s) 方法是在 Matcher 類中的一個靜態方法,用于將輸入字符串轉義,以便在替換操作中使用。
在 Java 中,正則表達式的替換操作通常使用 Matcher 類的 replaceAll(String replacement) 或 replaceFirst(String replacement) 方法。當替換字符串中包含一些特殊字符(如 $、\ 等)時,為了正確處理這些字符,需要對替換字符串進行轉義。
quoteReplacement(String s) 方法接受一個字符串參數 s,并返回一個轉義后的字符串,該字符串可以安全地用作替換操作的替換字符串。
public class RegTest {
public static void main(String[] args) {
String input = "Hello $ World";
String replacement = Matcher.quoteReplacement("$1");
String result = input.replaceAll("\\$", replacement);
System.out.println(replacement); //輸出:\$1
System.out.println(result); // 輸出:Hello $1 World
}
}
/*
運行結果:
\$1
Hello $1 World
*/
代碼判斷輸入字符串 s 中是否包含\和 $ 字符,即(s.indexOf('\') == -1) && (s.indexOf('$') == -1)。如果不包含任何特殊字符,則直接返回原始字符串s。
如果輸入字符串中包含了\或$字符,則進入循環處理。代碼使用一個 StringBuilder 對象 sb 來構建轉義后的字符串。通過遍歷輸入字符串的每個字符,將特殊字符\或$進行轉義處理,并添加到 sb 中。
具體地,當遇到特殊字符時,代碼使用 sb.append('\'); 將一個反斜杠字符添加到 sb 中,以進行轉義。然后,將當前字符 c 添加到 sb 中。
最后,循環結束后,代碼通過 sb.toString() 方法將 StringBuilder 轉換為字符串,并返回轉義后的結果。
(13)public boolean find()
說明:find() 方法是在 Matcher 類中的一個公共方法,用于在輸入字符串中查找與正則表達式模式匹配的下一個子序列
在 Java 中,Matcher 對象表示了對某個輸入字符串進行正則表達式匹配的狀態。find() 方法通過在輸入字符串中尋找與模式匹配的下一個子序列,來進行匹配操作。
該方法返回一個布爾值,如果在輸入字符串中找到了匹配的子序列,則返回 true,否則返回 false。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String regex = "\\d+";
String input = "12345";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Match found: " + matcher.group());
} else {
System.out.println("No match found.");
}
}
}
/*
運行結果:
Match found: 12345
*/
我們使用之前提到的方式創建了一個 Matcher 對象,并調用 find() 方法進行匹配操作。
如果匹配成功(即在輸入字符串中找到了匹配的子序列),則通過 matcher.group() 方法獲取匹配的結果,并打印輸出。否則,輸出未找到匹配。
(14)public boolean find(int start)
說明:find(int start) 方法是在 Matcher 類中的一個公共方法,用于在輸入字符串中從指定位置開始查找與正則表達式模式匹配的下一個子序列。
該方法接受一個整數參數 start,表示開始查找的位置索引。它會從指定位置開始在輸入字符串中查找與正則表達式模式匹配的下一個子序列。
find(int start) 方法返回一個布爾值,如果在指定位置之后的輸入字符串中找到了匹配的子序列,則返回 true,否則返回 false。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String regex = "\\d+";
String input = "12345";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
int start = 2; // 從索引 2 開始查找
if (matcher.find(start)) {
System.out.println("Match found: " + matcher.group());
} else {
System.out.println("No match found.");
}
}
}
/*
運行結果:
Match found: 345
*/
我們使用之前提到的方式創建了一個 Matcher 對象,并定義了一個開始查找的位置索引 start。
然后,我們調用 find(int start) 方法并傳入 start 參數來執行匹配操作。如果在指定位置之后的輸入字符串中找到了匹配的子序列,則通過 matcher.group() 方法獲取匹配的結果,并打印輸出。否則,輸出未找到匹配。
(15)public String group()
說明:group() 方法是在 Matcher 類中的一個公共方法,用于返回與最后一次匹配操作相匹配的字符串。
在執行匹配操作后,如果 find() 方法返回 true,則表示找到了匹配的子序列。此時,可以使用 group() 方法獲取最后一次匹配操作所匹配的字符串。
group() 方法返回一個字符串,即最后一次匹配操作所匹配的子序列。
public class RegTest {
public static void main(String[] args) {
String regex = "\\d";
String input = "12345";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while(matcher.find()){
System.out.println("Match found: " + matcher.group());
}
}
}
/*
運行結果:
Match found: 1
Match found: 2
Match found: 3
Match found: 4
Match found: 5
*/
(16)public String group(int group)
說明:group(int group) 方法是在 Matcher 類中的一個公共方法,用于返回與最后一次匹配操作中指定組號相匹配的字符串。
在正則表達式中,使用圓括號 () 可以創建捕獲組(Capture Group)。當進行匹配操作時,每個捕獲組都有一個對應的組號,從 1 開始遞增。group(int group) 方法接受一個整數參數 group,表示要獲取的捕獲組的組號。
group(int group) 方法返回一個字符串,即最后一次匹配操作中指定組號所匹配的子序列。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String regex = "(\\d+)-(\\w+)";
String input = "12345-abcd";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("First group: " + matcher.group(1));
System.out.println("Second group: " + matcher.group(2));
} else {
System.out.println("No match found.");
}
}
}
/*
運行結果:
First group: 12345
Second group: abcd
*/
我們使用之前提到的方式創建了一個 Matcher 對象,并調用 find() 方法進行匹配操作。
如果匹配成功(即在輸入字符串中找到了匹配的子序列),則通過 matcher.group(int group) 方法獲取指定組號的匹配結果,并打印輸出。這里分別獲取了第一個捕獲組和第二個捕獲組的結果。不指定捕獲組名稱,默認捕獲組從1開始遞增編號
group(int group) 方法的作用是返回與最后一次匹配操作中指定組號相匹配的字符串。它可以用于獲取指定組號的匹配結果并進行后續處理。注意,組號必須大于等于 1,且不能超過實際捕獲組的數量,否則會拋出 IndexOutOfBoundsException 異常.
(17)public String group(String name)
說明:group(String name) 方法是在 Matcher 類中的一個公共方法,用于返回與最后一次匹配操作中指定命名組名相匹配的字符串。
在正則表達式中,可以使用命名捕獲組(Named Capture Group)來標識和引用特定的子表達式。每個命名捕獲組都有一個唯一的名稱,可以通過該名稱來引用對應的匹配結果。
group(String name) 方法接受一個字符串參數 name,表示要獲取的命名捕獲組的名稱。
group(String name) 方法返回一個字符串,即最后一次匹配操作中指定命名組名所匹配的子序列。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String regex = "(?<number>\\d+)-(?<word>\\w+)";
String input = "12345-abcd";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.find()) {
System.out.println("Number group: " + matcher.group("number"));
System.out.println("Word group: " + matcher.group("word"));
} else {
System.out.println("No match found.");
}
}
}
/*
運行結果:
Number group: 12345
Word group: abcd
*/
我們使用之前提到的方式創建了一個 Matcher 對象,并調用 find() 方法進行匹配操作。
如果匹配成功(即在輸入字符串中找到了匹配的子序列),則通過 matcher.group(String name) 方法獲取指定命名組名的匹配結果,并打印輸出。這里分別獲取了名為 “number” 的命名捕獲組和名為 “word” 的命名捕獲組的結果。
group(String name) 方法的作用是返回與最后一次匹配操作中指定命名組名相匹配的字符串。它可以用于獲取指定命名組名的匹配結果并進行后續處理。如果沒有找到指定的命名組名,或者命名組名不合法,會拋出 IllegalArgumentException 異常.
(18)public boolean matches()
說明:matches() 方法是在 Matcher 類中的一個公共方法,用于嘗試將整個輸入序列與正則表達式進行匹配。
該方法會嘗試將整個輸入序列與正則表達式進行匹配,而不僅僅是尋找匹配的子序列。只有當整個輸入序列完全匹配正則表達式時,matches() 方法才返回 true,否則返回 false。
public class RegTest {
public static void main(String[] args) {
String regex = "\\d\\d\\d";
String input = "12345";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
System.out.println("Input matches the regular expression.");
} else {
System.out.println("Input does not match the regular expression.");
}
}
}
/*
運行結果:
Input does not match the regular expression.
*/
因為上面的正則表達式無法完全匹配輸入的12345,所以matches返回的false
(19)public Pattern pattern()
說明:pattern() 方法是在 Matcher 類中的一個公共方法,用于返回與當前 Matcher 對象關聯的正則表達式模式。
正則表達式模式通過 Pattern 類的實例來表示。pattern() 方法返回的就是與當前 Matcher 對象關聯的 Pattern 實例。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String regex = "\\d+";
String input = "12345";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
Pattern associatedPattern = matcher.pattern();
System.out.println("Associated pattern: " + associatedPattern.pattern());
}
}
/*
運行結果:
Associated pattern: \d+
*/
我們首先創建了一個 Pattern 對象,用于表示正則表達式模式。然后,我們將該模式與輸入字符串進行匹配操作,得到對應的 Matcher 對象。
接下來,我們調用 pattern() 方法獲取與當前 Matcher 對象關聯的正則表達式模式,并將其打印輸出。
(20)public String replaceAll(String replacement)
說明:replaceAll(String replacement) 方法是在 Matcher 類中的一個公共方法,用于將匹配到的子序列替換為指定的字符串。
該方法會查找輸入字符串中與正則表達式模式匹配的所有子序列,并將其替換為指定的字符串 replacement。
replaceAll(String replacement) 方法接受一個字符串參數 replacement,表示要替換匹配子序列的字符串。
replaceAll() 方法返回一個新的字符串,其中所有匹配的子序列都被替換為指定的字符串。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String regex = "\\d+";
String input = "Hello 123 World 456";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
String replacedString = matcher.replaceAll("X");
System.out.println("Replaced string: " + replacedString);
}
}
/*
輸出內容:
Replaced string: Hello X World X
*/
們使用之前提到的方式創建了一個 Matcher 對象,并調用 replaceAll(String replacement) 方法進行替換操作。
該示例中,正則表達式模式\d+ 可以匹配連續的數字。我們將輸入字符串中所有匹配到的數字替換為字符 “X”。
(21)public String replaceAll(Function<MatchResult, String> replacer) (java9/java1.9)
說明:String replaceAll(Function<MatchResult, String> replacer) 方法是在 Matcher 類中提供的一個功能,用于基于指定的模式替換字符串的部分內容。
它接受一個 函數式接口Function 參數 replacer,該參數用于確定每個匹配子串的替換值。replacer 函數接受一個 MatchResult 對象,表示當前的匹配結果,并返回替換后的字符串。
import java.util.function.Function;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MatcherReplaceAllExample {
public static void main(String[] args) {
String text = "Hello, world! How are you?";
// Define a regular expression pattern
Pattern pattern = Pattern.compile("\\b\\w{3}\\b");
// Create a matcher from the input text
Matcher matcher = pattern.matcher(text);
// Use replaceAll with a lambda expression as the replacer
//這里表示在調用函數式接口的方法的時候,將每次匹配的內容以大寫的形式返回
String result = matcher.replaceAll(match -> match.group().toUpperCase());
System.out.println(result);
}
}
/*
運行結果:
HELLO, WORLD! HOW ARE YOU?
*/
(22)public int start()
說明:返回上次匹配到內容的初始索引,如果上次匹配沒有內容,拋出異常。
String text = "Hello, world! How are you?";
// Define a regular expression pattern
Pattern pattern = Pattern.compile("\\b\\w{3}\\b");
// Create a matcher from the input text
Matcher matcher = pattern.matcher(text);
while(matcher.find()){
System.out.println("當前匹配內容:" + matcher.group() +",當前匹配的索引是:" + matcher.start());
}
}
}
/*
運行結果:
當前匹配內容:How,當前匹配的索引是:14
當前匹配內容:are,當前匹配的索引是:18
當前匹配內容:you,當前匹配的索引是:22
*/
(23)public int start(int group)
說明:和public String group(int group)類似,上一次匹配結果,捕獲組次序為group的的索引值。
(24)public int start(String name)
說明:和public String group(String Name)類似,上一次匹配結果,捕獲組名稱為name的的索引值。
(25)public int end()
說明:返回上一次匹配結果的結束索引位置,如果上次沒有匹配,那么報錯
(26)public int end(int group)
說明:和public String group(int group)類似,不做過多解釋
(27)public int end(String name)
說明:和public String group(String name)類似,不做過多解釋
(28)public int groupCount()
說明:
Matcher類的groupCount()方法是用于獲取匹配器中捕獲組的數量
String input = "Hello World";
Pattern pattern = Pattern.compile("(Hello) (World)");
Matcher matcher = pattern.matcher(input);
int count = matcher.groupCount();
System.out.println("Number of capturing groups: " + count);
/*
運行結果:
Number of capturing groups: 2
*/
我們使用正則表達式模式"(Hello) (World)“來創建一個Matcher對象。然后,我們使用groupCount()方法獲取匹配器中的捕獲組數量,并將結果打印出來。在這個例子中,正則表達式包含兩個捕獲組,因此輸出是"Number of capturing groups: 2”。
(29)public int groupCount(int group)
說明:和public String group(int group)類似,不做過多解釋
(30)public int groupCount(String name)
說明:和public String group(String name)類似,不做過多解釋
(31)public boolean lookingAt()
說明:lookingAt()是Matcher類中的一個方法,用于檢查輸入字符串的起始部分是否與正則表達式模式匹配。
String input = "Hello World";
Pattern pattern = Pattern.compile("Hello");
Matcher matcher = pattern.matcher(input);
boolean isLookingAt = matcher.lookingAt();
System.out.println("Looking at: " + isLookingAt);
/*
運行結果:
Looking at: true
*/
如果將input改為String input = "123Hello World";,則會報錯失敗。
(32)public Matcher region(int start, int end)
說明:Matcher類的region()方法用于設置匹配器的區域范圍,即指定在輸入字符串中進行匹配操作的起始位置和結束位置。返回值為Matcher對象本身,因此可以進行鏈式調用。
參數說明:
String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input).region(6, 11);
System.out.println("Matches: " + matcher.toString());
/*
運行結果:
Matches: java.util.regex.Matcher[pattern=World region=6,11 lastmatch=]
*/
(33)public int regionEnd()
說明:regionEnd()是Matcher類中的一個方法,用于返回匹配器當前設置的區域范圍的結束位置(不包括)
String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);
matcher.region(6, 11);
int regionEnd = matcher.regionEnd();
System.out.println("Region end: " + regionEnd);
/*
運行結果:
Region end: 11
*/
(34)public int regionStart()
說明:regionStart() 是 Matcher 類中的一個方法,用于返回匹配器當前設置的區域范圍的起始位置。
String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);
matcher.region(6, 11);
int regionStart = matcher.regionStart();
System.out.println("Region start: " + regionStart);
/*
運行結果:
Region start: 6
*/
(35)public String replaceFirst(String replacement)
說明:replaceFirst(String replacement) 是 Matcher 類中的一個方法,用于將匹配到的第一個子字符串替換為指定的替換字符串。
String input = "Hello World World World!";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);
String replacedString = matcher.replaceFirst("Universe");
System.out.println("Replaced string: " + replacedString);
/*
運行結果:
Replaced string: Hello Universe World World!
*/
(36)public String replaceFirst(Function<MatchResult, String> replacer)
說明:類似于上面的public String replaceAll(Function<MatchResult, String> replacer)
String input = "Hello World World World!";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);
String replacedString = matcher.replaceFirst(match -> match.group().toUpperCase());
System.out.println("Replaced string: " + replacedString);
/*
運行結果:
Replaced string: Hello WORLD World World!
*/
(37)public Matcher reset()
說明:
reset() 是 Matcher 類中的一個方法,用于重置匹配器的狀態,將其重新設置為初始狀態。
String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);
matcher.find();
System.out.println("First match: " + matcher.group());
matcher.reset();
matcher.find();
System.out.println("Reset match: " + matcher.group());
/*
運行結果:
First match: World
Reset match: World
*/
我們首先使用正則表達式模式"World"創建一個 Matcher 對象,并將其應用于輸入字符串"Hello World"。然后,我們使用 find() 方法進行一次匹配操作,并打印出第一個匹配到的子字符串 “World”。接下來,我們使用 reset() 方法重置匹配器的狀態,將其恢復到初始狀態。再次使用 find() 方法進行匹配操作,可以看到匹配器又重新從輸入字符串中找到了與正則表達式匹配的子字符串 “World”。
(38)public Matcher reset(CharSequence input)
說明:reset(CharSequence input) 是 Matcher 類中的一個方法,用于重置匹配器的狀態,并將新的輸入字符序列應用于匹配器
String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);
matcher.find();
System.out.println("First match: " + matcher.group());
CharSequence newInput = "Hello Universe";
matcher.reset(newInput);
matcher.find();
System.out.println("Reset match: " + matcher.group());
/*
運行結果:
First match: World
Reset match: Universe
*/
(39)public Matcher reset(CharSequence input)
說明:toMatchResult() 是 Matcher 類中的一個方法,用于返回當前匹配操作的結果作為 MatchResult 對象。
String input = "Hello World";
Pattern pattern = Pattern.compile("World");
Matcher matcher = pattern.matcher(input);
matcher.find();
MatchResult matchResult = matcher.toMatchResult();
System.out.println("Matched substring: " + matchResult.group());
System.out.println("Start index: " + matchResult.start());
System.out.println("End index: " + matchResult.end());
/*
輸出:
Matched substring: World
Start index: 6
End index: 11
*/
我們首先使用正則表達式模式"World"創建一個 Matcher 對象,并將其應用于輸入字符串"Hello World"。然后,我們使用 find() 方法進行一次匹配操作。接下來,我們使用 toMatchResult() 方法獲取當前匹配操作的結果作為 MatchResult 對象。通過 MatchResult 對象,我們可以訪問匹配到的子字符串、起始位置和結束位置等信息,并將其打印出來。
請注意,toMatchResult() 方法返回的是一個 MatchResult 對象,其中包含了有關匹配結果的各種信息。通過 MatchResult 對象,您可以獲取匹配到的子字符串以及它在輸入字符串中的起始位置和結束位置等相關信息。
(40)public Matcher usePattern(Pattern newPattern)
說明:usePattern(Pattern newPattern) 是 Matcher 類中的一個方法,用于將匹配器切換到一個新的正則表達式模式
該方法的函數簽名如下:
public Matcher usePattern(Pattern newPattern)
參數 newPattern 表示要切換到的新的正則表達式模式。
返回值為 Matcher 對象本身,因此可以進行鏈式調用
String input = "Hello World";
Pattern pattern1 = Pattern.compile("World");
Matcher matcher = pattern1.matcher(input);
matcher.find();
System.out.println("First match: " + matcher.group());
Pattern pattern2 = Pattern.compile("Hello");
matcher.usePattern(pattern2);
matcher.find();
System.out.println("New pattern match: " + matcher.group());
/*
運行結果:
First match: World
New pattern match: Hello
*/
我們首先使用正則表達式模式 “World” 創建一個 Matcher 對象,并將其應用于輸入字符串 “Hello World”。然后,我們使用 find() 方法進行一次匹配操作,并打印出第一個匹配到的子字符串 “World”。接下來,我們創建了另一個正則表達式模式 “Hello” 并使用 usePattern() 方法將匹配器切換到這個新的模式。再次使用 find() 方法進行匹配操作,可以看到匹配器從新的模式中找到了與之匹配的子字符串 “Hello”。
請注意,usePattern(Pattern newPattern) 方法用于切換 Matcher 對象的正則表達式模式。通過使用不同的模式,您可以重復使用同一個 Matcher 對象進行多個不同模式的匹配操作。調用此方法后,匹配器的狀態將被重置,并從新的模式開始進行匹配操作。
正則表達式是一種用來匹配字符串的強有力的武器
它的設計思想是用一種描述性的語言定義一個規則,凡是符合規則的字符串,我們就認為它“匹配”了,否則,該字符串就是不合法的
根據正則表達式語法規則,大部分字符僅能夠描述自身,這些字符被稱為普通字符,如所有的字母、數字等。
元字符就是擁有特動功能的特殊字符,大部分需要加反斜杠進行標識,以便于普通字符進行區別,而少數元字符,需要加反斜杠,以便轉譯為普通字符使用。JavaScript 正則表達式支持的元字符如表所示。
在 JavaScript中,正則表達式也是對象,構建正則表達式有兩種方式:
const re = /\d+/g;
const re = new RegExp("\\d+","g");
const rul = "\\d+"
const re1 = new RegExp(rul,"g");
使用構建函數創建,第一個參數可以是一個變量,遇到特殊字符\需要使用\進行轉義
表示字符的方法有多種,除了可以直接使用字符本身外,還可以使用 ASCII 編碼或者 Unicode 編碼來表示。
下面使用 ASCII 編碼定義正則表達式直接量。
var r = /\x61/;var s = "JavaScript";var a = s.match(s);
由于字母 a 的 ASCII 編碼為 97,被轉換為十六進制數值后為 61,因此如果要匹配字符 a,就應該在前面添加“\x”前綴,以提示它為 ASCII 編碼。
除了十六進制外,還可以直接使用八進制數值表示字符。
var r = /1/;var s = "JavaScript";var a = s.match(r);
使用十六進制需要添加“\x”前綴,主要是為了避免語義混淆,而八進制則不需要添加前綴。
ASCII 編碼只能夠匹配有限的單字節字符,使用 Unicode 編碼可以表示雙字節字符。Unicode 編碼方式:“\u”前綴加上 4 位十六進制值。
var r = "/\u0061/";var s = "JavaScript";var a = s.match(s);
在 RegExp() 構造函數中使用元字符時,應使用雙斜杠。
var r = new RegExp("\u0061");
RegExp() 構造函數的參數只接受字符串,而不是字符模式。在字符串中,任何字符加反斜杠還表示字符本身,如字符串“\u”就被解釋為 u 本身,所以對于“\u0061”字符串來說,在轉換為字符模式時,就被解釋為“u0061”,而不是“\u0061”,此時反斜杠就失去轉義功能。解決方法:在字符 u 前面加雙反斜杠。
常見的校驗規則如下:
規則 | 描述 |
\ | 轉義 |
^ | 匹配輸入的開始 |
$ | 匹配輸入的結束 |
* | 匹配前一個表達式 0 次或多次 |
+ | 匹配前面一個表達式 1 次或者多次。等價于 {1,} |
? | 匹配前面一個表達式 0 次或者 1 次。等價于{0,1} |
. | 默認匹配除換行符之外的任何單個字符 |
x(?=y) | 匹配'x'僅僅當'x'后面跟著'y'。這種叫做先行斷言 |
(?<=y)x | 匹配'x'僅當'x'前面是'y'.這種叫做后行斷言 |
x(?!y) | 僅僅當'x'后面不跟著'y'時匹配'x',這被稱為正向否定查找 |
(?<!y)x | 僅僅當'x'前面不是'y'時匹配'x',這被稱為反向否定查找 |
x|y | 匹配‘x’或者‘y’ |
{n} | n 是一個正整數,匹配了前面一個字符剛好出現了 n 次 |
{n,} | n是一個正整數,匹配前一個字符至少出現了n次 |
{n,m} | n 和 m 都是整數。匹配前面的字符至少n次,最多m次 |
[xyz] | 一個字符集合。匹配方括號中的任意字符 |
[^xyz] | 匹配任何沒有包含在方括號中的字符 |
\b | 匹配一個詞的邊界,例如在字母和空格之間 |
\B | 匹配一個非單詞邊界 |
\d | 匹配一個數字 |
\D | 匹配一個非數字字符 |
\f | 匹配一個換頁符 |
\n | 匹配一個換行符 |
\r | 匹配一個回車符 |
\s | 匹配一個空白字符,包括空格、制表符、換頁符和換行符 |
\S | 匹配一個非空白字符 |
\w | 匹配一個單字字符(字母、數字或者下劃線) |
\W | 匹配一個非單字字符 |
標志 | 描述 |
g | 全局搜索。 |
i | 不區分大小寫搜索。 |
m | 多行搜索。 |
s | 允許 . 匹配換行符。 |
u | 使用unicode碼的模式進行匹配。 |
y | 執行“粘性(sticky)”搜索,匹配從目標字符串的當前位置開始。 |
使用方法如下:
var re = /pattern/flags;
var re = new RegExp("pattern", "flags");
在了解下正則表達式基本的之外,還可以掌握幾個正則表達式的特性:
在了解貪婪模式前,首先舉個例子:
const reg = /ab{1,3}c/
在匹配過程中,嘗試可能的順序是從多往少的方向去嘗試。首先會嘗試bbb,然后再看整個正則是否能匹配。不能匹配時,吐出一個b,即在bb的基礎上,再繼續嘗試,以此重復
如果多個貪婪量詞挨著,則深度優先搜索
const string = "12345";
const regx = /(\d{1,3})(\d{1,3})/;
console.log( string.match(reg) );
// => ["12345", "123", "45", index: 0, input: "12345"]
其中,前面的\d{1,3}匹配的是"123",后面的\d{1,3}匹配的是"45"
惰性量詞就是在貪婪量詞后面加個問號。表示盡可能少的匹配
var string = "12345";
var regex = /(\d{1,3}?)(\d{1,3})/;
console.log( string.match(regex) );
// => ["1234", "1", "234", index: 0, input: "12345"]
其中\d{1,3}?只匹配到一個字符"1",而后面的\d{1,3}匹配了"234"
分組主要是用過()進行實現,比如beyond{3},是匹配d字母3次。而(beyond){3}是匹配beyond三次
在()內使用|達到或的效果,如(abc | xxx)可以匹配abc或者xxx
反向引用,巧用$分組捕獲
let str = "John Smith";
// 交換名字和姓氏
console.log(str.replace(/(john) (smith)/i, '$2, $1')) // Smith, John
正則表達式常被用于某些方法,我們可以分成兩類:
方法 | 描述 |
exec | 一個在字符串中執行查找匹配的RegExp方法,它返回一個數組(未匹配到則返回 null)。 |
test | 一個在字符串中測試是否匹配的RegExp方法,它返回 true 或 false。 |
match | 一個在字符串中執行查找匹配的String方法,它返回一個數組,在未匹配到時會返回 null。 |
matchAll | 一個在字符串中執行查找所有匹配的String方法,它返回一個迭代器(iterator)。 |
search | 一個在字符串中測試匹配的String方法,它返回匹配到的位置索引,或者在失敗時返回-1。 |
replace | 一個在字符串中執行查找匹配的String方法,并且使用替換字符串替換掉匹配到的子字符串。 |
split | 一個使用正則表達式或者一個固定字符串分隔一個字符串,并將分隔后的子字符串存儲到數組中的 String 方法。 |
str.match(regexp) 方法在字符串 str 中找到匹配 regexp 的字符
如果 regexp 不帶有 g 標記,則它以數組的形式返回第一個匹配項,其中包含分組和屬性 index(匹配項的位置)、input(輸入字符串,等于 str)
let str = "I love JavaScript";
let result = str.match(/Java(Script)/);
console.log( result[0] ); // JavaScript(完全匹配)
console.log( result[1] ); // Script(第一個分組)
console.log( result.length ); // 2
// 其他信息:
console.log( result.index ); // 7(匹配位置)
console.log( result.input ); // I love JavaScript(源字符串)
如果 regexp 帶有 g 標記,則它將所有匹配項的數組作為字符串返回,而不包含分組和其他詳細信息
let str = "I love JavaScript";
let result = str.match(/Java(Script)/g);
console.log( result[0] ); // JavaScript
console.log( result.length ); // 1
如果沒有匹配項,則無論是否帶有標記 g ,都將返回 null
let str = "I love JavaScript";
let result = str.match(/HTML/);
console.log(result); // null
返回一個包含所有匹配正則表達式的結果及分組捕獲組的迭代器
const regexp = /t(e)(st(\d?))/g;
const str = 'test1test2';
const array = [...str.matchAll(regexp)];
console.log(array[0]);
// expected output: Array ["test1", "e", "st1", "1"]
console.log(array[1]);
// expected output: Array ["test2", "e", "st2", "2"]
返回第一個匹配項的位置,如果未找到,則返回 -1
let str = "A drop of ink may make a million think";
console.log( str.search( /ink/i ) ); // 10(第一個匹配位置)
這里需要注意的是,search 僅查找第一個匹配項
替換與正則表達式匹配的子串,并返回替換后的字符串。在不設置全局匹配g的時候,只替換第一個匹配成功的字符串片段
const reg1=/javascript/i;
const reg2=/javascript/ig;
console.log('hello Javascript Javascript Javascript'.replace(reg1,'js'));
//hello js Javascript Javascript
console.log('hello Javascript Javascript Javascript'.replace(reg2,'js'));
//hello js js js
使用正則表達式(或子字符串)作為分隔符來分割字符串
console.log('12, 34, 56'.split(/,\s*/)) // 數組 ['12', '34', '56']
regexp.exec(str) 方法返回字符串 str 中的 regexp 匹配項,與以前的方法不同,它是在正則表達式而不是字符串上調用的
根據正則表達式是否帶有標志 g,它的行為有所不同
如果沒有 g,那么 regexp.exec(str) 返回的第一個匹配與 str.match(regexp) 完全相同
如果有標記 g,調用 regexp.exec(str) 會返回第一個匹配項,并將緊隨其后的位置保存在屬性regexp.lastIndex 中。 下一次同樣的調用會從位置 regexp.lastIndex 開始搜索,返回下一個匹配項,并將其后的位置保存在 regexp.lastIndex 中
let str = 'More about JavaScript at https://javascript.info';
let regexp = /javascript/ig;
let result;
while (result = regexp.exec(str)) {
console.log( `Found ${result[0]} at position ${result.index}` );
// Found JavaScript at position 11
// Found javascript at position 33
}
查找匹配項,然后返回 true/false 表示是否存在
let str = "I love JavaScript";
// 這兩個測試相同
console.log( /love/i.test(str) ); // true
通過上面的學習,我們對正則表達式有了一定的了解
下面再來看看正則表達式一些案例場景:
驗證QQ合法性(5~15位、全是數字、不以0開頭):
const reg = /^[1-9][0-9]{4,14}$/
const isvalid = patrn.exec(s)
校驗用戶賬號合法性(只能輸入5-20個以字母開頭、可帶數字、“_”、“.”的字串):
var patrn=/^[a-zA-Z]{1}([a-zA-Z0-9]|[._]){4,19}$/;
const isvalid = patrn.exec(s)
將url參數解析為對象
const protocol = '(?<protocol>https?:)';
const host = '(?<host>(?<hostname>[^/#?:]+)(?::(?<port>\\d+))?)';
const path = '(?<pathname>(?:\\/[^/#?]+)*\\/?)';
const search = '(?<search>(?:\\?[^#]*)?)';
const hash = '(?<hash>(?:#.*)?)';
const reg = new RegExp(`^${protocol}\/\/${host}${path}${search}${hash}$`);
function execURL(url){
const result = reg.exec(url);
if(result){
result.groups.port = result.groups.port || '';
return result.groups;
}
return {
protocol:'',host:'',hostname:'',port:'',
pathname:'',search:'',hash:'',
};
}
console.log(execURL('https://localhost:8080/?a=b#xxxx'));
protocol: "https:"
host: "localhost:8080"
hostname: "localhost"
port: "8080"
pathname: "/"
search: "?a=b"
hash: "#xxxx"
再將上面的search和hash進行解析
function execUrlParams(str){
str = str.replace(/^[#?&]/,'');
const result = {};
if(!str){ //如果正則可能配到空字符串,極有可能造成死循環,判斷很重要
return result;
}
const reg = /(?:^|&)([^&=]*)=?([^&]*?)(?=&|$)/y
let exec = reg.exec(str);
while(exec){
result[exec[1]] = exec[2];
exec = reg.exec(str);
}
return result;
}
console.log(execUrlParams('#'));// {}
console.log(execUrlParams('##'));//{'#':''}
console.log(execUrlParams('?q=3606&src=srp')); //{q: "3606", src: "srp"}
console.log(execUrlParams('test=a=b=c&&==&a='));//{test: "a=b=c", "": "=", a: ""}
1. dotAll模式(s選項)
這個特性已經在ECMAScript 2018正式發布了。
默認情況下,.可以匹配任意字符,除了換行符:
/foo.bar/u.test('foo\nbar'); // false
另外,.不能匹配Unicode字符,需要使用u選項啟用Unicode模式才行。
ES2018引入了dotAll模式,通過s選項可以啟用,這樣,.就可以匹配換行符了。
/foo.bar/su.test('foo\nbar'); // true
2. Lookbehind斷言
這個特性已經在ECMAScript 2018正式發布了。
ECMAScript目前僅支持lookahead斷言。
下面示例是Positive lookahead,匹配字符串“42 dollars”中緊跟著是”dollars”的數字:
const pattern = /\d+(?= dollars)/u;
const result = pattern.exec('42 dollars');
console.log(result[0]); // 打印42
下面示例是Negative lookahead,匹配字符串“42 pesos”中緊跟著的不是”dollars”的數字:
const pattern = /\d+(?! dollars)/u;
const result = pattern.exec('42 pesos');
console.log(result[0]); // 打印42
ES2018添加了lookbehind斷言。
下面示例是Positive lookbehind,匹配字符串“”中前面是”$”的數字:
const pattern = /(?<=\$)\d+/u;
const result = pattern.exec('$42');
console.log(result[0]); // 打印42
下面示例是Negative lookbehind,匹配字符串“”中前面不是是”$”的數字:
const pattern = /(?<!\$)\d+/u;
const result = pattern.exec('€42');
console.log(result[0]); // 打印42
Fundebug專注于網頁、微信小程序、微信小游戲,支付寶小程序,React Native,Node.js和Java線上BUG實時監控,歡迎免費試用
3. Named capture groups
這個特性已經在ECMAScript 2018正式發布了。
目前,正則表達式中小括號匹配的分組是通過數字編號的:
const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-01-25');
console.log(result[0]); // 打印"2017-01-25"
console.log(result[1]); // 打印"2017"
console.log(result[2]); // 打印"01"
console.log(result[3]); // 打印"25"
這樣很方便,但是可讀性很差,且不易維護。一旦正則表達式中小括號的順序有變化時,我們就需要更新對應的數字編號。
ES2018添加named capture groups, 可以指定小括號中匹配內容的名稱,這樣可以提高代碼的可讀性,也便于維護。
const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-01-25');
console.log(result.groups.year); // 打印"2017"
console.log(result.groups.month); // 打印"01"
console.log(result.groups.day); // 打印"25"
4. Unicode property escapes
這個特性已經在ECMAScript 2018正式發布了。
Unicode標準為每一個字符分配了多個屬性。比如,當你要匹配希臘語字符時,則可以搜索Script_Extensions屬性為Greek的字符。
Unicode property escapes使得我們可以使用ECMAScript正則表達式直接匹配Unicode字符的屬性:
const regexGreekSymbol = /\p{Script_Extensions=Greek}/u;
console.log(regexGreekSymbol.test('π')); // 打印true
5. String.prototype.matchAll
這個特性還處在Stage 3 Draft
g和y選項通常用于匹配一個字符串,然后遍歷所有匹配的子串,包括小括號匹配的分組。String.prototype.matchAll讓這個操作變得更加簡單了。
const string = 'Magic hex numbers: DEADBEEF CAFE 8BADF00D';
const regex = /\b[0-9a-fA-F]+\b/g;
for (const match of string.matchAll(regex)) {
console.log(match);
}
每一個迭代所返回的match對象與regex.exec(string)所返回的結果相同:
// Iteration 1:
[
'DEADBEEF',
index: 19,
input: 'Magic hex numbers: DEADBEEF CAFE 8BADF00D'
]
// Iteration 2:
[
'CAFE',
index: 28,
input: 'Magic hex numbers: DEADBEEF CAFE 8BADF00D'
]
// Iteration 3:
[
'8BADF00D',
index: 33,
input: 'Magic hex numbers: DEADBEEF CAFE 8BADF00D'
]
注意,這個特性還處在Stage 3 Draft,因此還存在變化的可能性,示例代碼是根據最新的提案寫的。另外,瀏覽器也還沒有支持這個特性。String.prototype.matchAll最快可以被加入到ECMAScript 2019中。
6. 規范RegExp遺留特性
這個提案還處在Stage 3 Draft
這個提案規范了RegExp的遺留特性,比如RegExp.prototype.compile方法以及它的靜態屬性從RegExp.到RegExp.。雖然這些特性已經棄用(deprecated)了,但是為了兼容性我們不能將他們去。因此,規范這些RegExp遺留特性是最好的方法。因此,這個提案有助于保證兼容性。
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor']
return valid_map.indexOf(str.trim()) >= 0
}
/**
* @param {string} url
* @returns {Boolean}
*/
export function validURL(url) {
const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
return reg.test(url)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validLowerCase(str) {
const reg = /^[a-z]+$/
return reg.test(str)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUpperCase(str) {
const reg = /^[A-Z]+$/
return reg.test(str)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
}
/**
* @param {string} email
* @returns {Boolean}
*/
export function validEmail(email) {
const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return reg.test(email)
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function isString(str) {
if (typeof str === 'string' || str instanceof String) {
return true
}
return false
}
/**
* @param {Array} arg
* @returns {Boolean}
*/
export function isArray(arg) {
if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]'
}
return Array.isArray(arg)
}
TS版
/**
* @param {string} path
* @returns {Boolean}
*/
export function isExternal(path) {
return /^(https?:|mailto:|tel:)/.test(path);
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUsername(str) {
const valid_map = ['admin', 'editor'];
return valid_map.indexOf(str.trim()) >= 0;
}
/**
* @param {string} url
* @returns {Boolean}
*/
export function validURL(url) {
const reg =
/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/;
return reg.test(url);
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validLowerCase(str) {
const reg = /^[a-z]+$/;
return reg.test(str);
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validUpperCase(str) {
const reg = /^[A-Z]+$/;
return reg.test(str);
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function validAlphabets(str) {
const reg = /^[A-Za-z]+$/;
return reg.test(str);
}
/**
* @param {string} email
* @returns {Boolean}
*/
export function validEmail(email) {
const reg =
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return reg.test(email);
}
/**
* @param {string} phone
* @returns {Boolean}
*/
export function validPhone(phone) {
const reg = /^1[3-9][0-9]{9}$/;
return reg.test(phone);
}
/**
* @param {string} str
* @returns {Boolean}
*/
export function isString(str) {
if (typeof str === 'string' || str instanceof String) {
return true;
}
return false;
}
/**
* @param {Array} arg
* @returns {Boolean}
*/
export function isArray(arg) {
if (typeof Array.isArray === 'undefined') {
return Object.prototype.toString.call(arg) === '[object Array]';
}
return Array.isArray(arg);
}
// [修改]-新增-開始
/**
* 英文驗證
* @param min
* @param max
* @param value
*/
export function english(value: string, min = 6, max = 12): boolean {
return new RegExp('^[a-z|A-Z]{' + min + ',' + max + '}$').test(value);
}
/**
* 中文驗證
* @param min
* @param max
* @param value
*/
export function chinese(value: string, min = 2, max = 12): boolean {
return new RegExp('^[\u4e00-\u9fa5]{' + min + ',' + max + '}$').test(value);
}
/**
* 非中文
* @param value 內容
* @returns boolean
*/
export function notChinese(value: string): boolean {
return !/[\u4e00-\u9fa5]/.test(value);
}
/**
* 必需數字
* @param min
* @param max
* @param value
*/
export function number(value: string, min = 1, max = 20): boolean {
return new RegExp('^d{' + min + ',' + max + '}$').test(value);
}
/**
* 必需小數點最大值
* @param min
* @param max
* @param value
*/
export function precision(value: string, max = 8, precision = 8): boolean {
return new RegExp(
'(^[0-9]{1,' + max + '}$)|(^[0-9]{1,' + max + '}[.]{1}[0-9]{1,' + precision + '}$)',
).test(value);
}
/**
* 復雜密碼驗證
* @param value
*/
export function pwd(value: string): boolean {
if (value && value.length > 15) {
const en = /[a-z]/.test(value);
const num = /[0-9]/.test(value);
const daxie = /[A-Z]/.test(value);
const teshu = /[~!@#$%^&*()_+=-\[\]\\,.\/;':{}]/.test(value);
return en && num && daxie && teshu;
}
return false;
}
// [修改]-新增-結束
給大家分享我收集整理的各種學習資料,前端小白交學習流程,入門教程等回答-下面是學習資料參考。
前端學習交流、自學、學習資料等推薦 - 知乎
*請認真填寫需求信息,我們會在24小時內與您取得聯系。