1.單個(gè)字符的匹配規(guī)則如下:
| 正則表達(dá)式 | 規(guī)則 | 可以匹配 |
|---|---|---|
A |
指定字符 | A |
\u548c |
指定Unicode字符 | 和 |
. |
任意字符 |
a,b,&,0
|
\d |
數(shù)字0~9 |
0~9
|
\w |
大小寫字母,數(shù)字和下劃線 |
a`z`,`A`Z,0~9,_
|
\s |
空格、Tab鍵 | 空格,Tab |
\D |
非數(shù)字 |
a,A,&,_,…… |
\W |
非\w |
&,@,中,…… |
\S |
非\s |
a,A,&,_,…… |
2.多個(gè)字符的匹配規(guī)則如下
| 正則表達(dá)式 | 規(guī)則 | 可以匹配 |
|---|---|---|
A* |
任意個(gè)數(shù)字符 | 空,A,AA,AAA,…… |
A+ |
至少1個(gè)字符 |
A,AA,AAA,…… |
A? |
0個(gè)或1個(gè)字符 | 空,A
|
A{3} |
指定個(gè)數(shù)字符 | AAA |
A{2,3} |
指定范圍個(gè)數(shù)字符 |
AA,AAA
|
A{2,} |
至少n個(gè)字符 |
AA,AAA,AAAA,…… |
A{0,3} |
最多n個(gè)字符 | 空,A,AA,AAA
|
3.匹配指定范圍
比如1A2b3c,我們可以這樣寫:[0-9a-fA-F],它表示一共可以匹配以下任意范圍的字符:
0-9:字符0~9;
a-f:字符a~f;
A-F:字符A~F。
3.1排除法
? ^ 不包含指定范圍的字符
-
假設(shè)我們要匹配任意字符,但不包括數(shù)字,可以寫
[^1-9]{3}:可以匹配
"ABC",因?yàn)椴话址?code>1~9;可以匹配
"A00",因?yàn)椴话址?code>1~9;不能匹配
"A01",因?yàn)榘址?code>1;不能匹配
"A05",因?yàn)榘址?code>5。
4.或規(guī)則匹配
用|連接的兩個(gè)正則規(guī)則是或規(guī)則,例如,AB|CD表示可以匹配AB或CD
5.實(shí)用括號
現(xiàn)在我們想要匹配字符串learn java、learn php和learn go怎么辦?一個(gè)最簡單的規(guī)則是learn\sjava|learn\sphp|learn\sgo,但是這個(gè)規(guī)則太復(fù)雜了,可以把公共部分提出來,然后用(...)把子規(guī)則括起來表示成learn\\s(java|php|go)。
var 使用括號匹配大寫 = "learn\\s([Jj]ava|[Gg]o|[Pp]hp)";
//匹配字符串learn Java、learn Php和learn Go的大小寫
6.分組匹配
正則匹配區(qū)號-電話號碼這個(gè)規(guī)則
\d{3,4}\-\d{6,8}
如果需要提取區(qū)號和電話號碼,需要將要提取的規(guī)則使用括號分組,把上述正則表達(dá)式變?yōu)?code>(\d{3,4})\-(\d{6,8})
public class Main {
public static void main(String[] args) {
Pattern p = Pattern.compile("(\\d{3,4})\\-(\\d{7,8})");
Matcher m = p.matcher("010-12345678");
if (m.matches()) {
System.out.println(m.group(0));//010-12345678
String g1 = m.group(1);////010
String g2 = m.group(2);//12345678
System.out.println(g1);
System.out.println(g2);
} else {
System.out.println("匹配失敗!");
}
}
}
使用Matcher時(shí),必須首先調(diào)用matches()判斷是否匹配成功,匹配成功后,才能調(diào)用group()提取子串。
例子:
從字符串23:01:59提取時(shí)、分、秒
var time = "([0-1]\\d|2[0-3]):([0-5]\\d):([0-5]\\d)";
Pattern p1 = Pattern.compile(time);
Matcher m1 = p1.matcher("23:01:59");
if (m1.matches()) {
System.out.println(m1.group(1));
System.out.println(m1.group(2));
System.out.println(m1.group(3));
} else {
System.out.println("匹配失敗");
}
7.非貪婪匹配
給定一個(gè)字符串表示的數(shù)字,判斷該數(shù)字末尾0的個(gè)數(shù)??梢院苋菀椎貙懗鲈撜齽t表達(dá)式:(\d+)(0*)
"123000":3個(gè)0期望結(jié)果:123000實(shí)際結(jié)果:"123000""""10100":2個(gè)0期望結(jié)果:10100實(shí)際結(jié)果:"10100""""1001":0個(gè)0期望結(jié)果:1001""實(shí)際結(jié)果:"1001"""
這是因?yàn)檎齽t表達(dá)式默認(rèn)使用貪婪匹配:任何一個(gè)規(guī)則,它總是盡可能多地向后匹配,因此,\d+總是會把后面的0包含進(jìn)來。
要讓\d+盡量少匹配,讓0*盡量多匹配,我們就必須讓\d+使用非貪婪匹配。在規(guī)則\d+后面加個(gè)?即可表示非貪婪匹配。
改寫正則表達(dá)式如下(\d+?)(0*)" 因此,給定一個(gè)匹配規(guī)則,加上?后就變成了非貪婪匹配。
我們再來看這個(gè)正則表達(dá)式(\d??)(9*),注意\d?表示匹配0個(gè)或1個(gè)數(shù)字,后面第二個(gè)?表示非貪婪匹配,因此,給定字符串"9999",匹配到的兩個(gè)子串分別是""和"9999",因?yàn)閷τ?code>\d?來說,可以匹配1個(gè)9,也可以匹配0個(gè)9,但是因?yàn)楹竺娴?code>?表示非貪婪匹配,它就會盡可能少的匹配,結(jié)果是匹配了0個(gè)9。
8.搜索和替換
8.1 分割字符串
System.out.println(Arrays.toString("a b c".split("\\s")));//[a, b, c]
System.out.println(Arrays.toString("a b c".split("\\s")));//[a, b, "", c]
System.out.println(Arrays.toString("a,b ;; c".split("[\\,\\s\\;]+")));//[a, b, c]
8.2 搜索字符串
String s = "the quick brown fox jumps over the lazy dog.";
Pattern p3 = Pattern.compile("\\wo\\w");// \w匹配[A-Za-z0-9_]
Matcher m3 = p3.matcher(s);
while (m3.find()) {
String sub = s.substring(m3.start(), m3.end());
System.out.println(sub);
//row fox dog
}
我們獲取到Matcher對象后,不需要調(diào)用matches()方法(因?yàn)槠ヅ湔麄€(gè)串肯定返回false),而是反復(fù)調(diào)用find()方法,在整個(gè)串中搜索能匹配上\\wo\\w規(guī)則的子串,并打印出來。這種方式比String.indexOf()要靈活得多,因?yàn)槲覀兯阉鞯囊?guī)則是3個(gè)字符:中間必須是o,前后兩個(gè)必須是字符[A-Za-z0-9_]。
8.3 替換字符串
String s2 = "The quick\t\t brown fox jumps over the lazy dog.";
String r = s2.replaceAll("\\s+", " ");//將多個(gè)空格替換成一個(gè)
System.out.println(r); // "The quick brown fox jumps over the lazy dog."
8.4 反向引用
String s3 = "the quick brown fox jumps over the lazy dog.";
String r2 = s3.replaceAll("\\s([a-z]{4})\\s", "<b>$1</b>");
System.out.println(r2);//the quick brown fox jumps<b>over</b>the<b>lazy</b>dog.
它實(shí)際上把任何4字符單詞的前后用<b>xxxx</b>括起來。實(shí)現(xiàn)替換的關(guān)鍵就在于" <b>$1</b> ",它用匹配的分組子串([a-z]{4})替換了$1。
8.5 使用Map替換模板中的值
HashMap<String, String> map = new HashMap<>();
map.put("name", "Mary");
map.put("lang", "Java");
String model = "Hello, ${name}! You are learning ${lang}!";
Pattern pt = Pattern.compile("\\$\\{([a-z]+)}");
Matcher mt = pt.matcher(model);
StringBuilder sb = new StringBuilder();
while (mt.find()) {
//0->${name} 1->name
//0->${lang} 1->lang
//0 代表整個(gè)匹配的字段 1代表匹配字段中的第一個(gè)分組
mt.appendReplacement(sb, map.get(mt.group(1)));
}
mt.appendTail(sb);
System.out.println(sb.toString());