我们经常会需要编写代码来验证用户输入,比如输入是否是一个数字,是否是一个邮箱等等。编写这类代码一个简单有效的做法就是使用正则表达式。
正则表达式是一个字符串,用来描述匹配一个字符串集合的模式。我们可以使用正则表达式来匹配、替换和分割字符串。

匹配字符串

先说一下String类中matchs方法:乍一看,matches方法很像equals方法。

"Test".matches("Test");  //True
"Test".equals("Test");   //True

这两个方法返回的结果都是True,但是matches方法其实更强大。它不仅可以匹配上述代码固定的字符串,还可以匹配一个模式的字符串。

"Test True or False".matches("Test.*")   //True
"Test False or True".matches("Test.*")   //True

上述代码的“Test.*”就是一个正则表达式。它描述了一个字符串的模式:从Test开始,后面跟任意字符串。.*匹配的是任意0或多个字符。

正则表达式语法

正则表达式由字符和特殊符号构成。反斜杠是特殊字符(转义符),因此使用\d来表示\d(两次转义)。

正则表达式

匹配

示例

x

指定字符x

test->test

.

任意单个字符

test->t…t

(ab|cd)

ab或cd

asd->a(sd|qeicbn)

[abc]

a或b或c

test->te[asdf]t

[^abc]

除a或b或c以外的任何字符

test->te[^qwe]t

[a-z]

a到z的任何字符

test->t[a-z]st

[^a-z]

除a到z以外的任何字符

test->tes[^a-s]

[a-e[m-p]]

a到e或m到p

Test->[F-U[I-M]]es[f-u]

[a-e&&[c-p]]

a到e和c到p

Test->[A-O&&[R-Z]]es[a-z]

\d

一位数,同[0-9]

test1->test[\\d]

\D

一位非数字

test->[\\D]est

\w

单词字符

test->[\\w]es[\\w]

\W

非单词字符

test1->test[\\W]

\s

空白字符

tes t->tes\\st

\S

非空白字符

tes t->[\\S]es t

p*

p任意次出现

tttest->t*est ~ testtesttest->(test)*

p+

p至少出现一次

e->e+t* ~ test->(te)+.*

p?

p至多出现一次

test->t?est

p{n}

p恰好出现n次

test->t{1}e.*

p{n, }

p至少出现n次

tttt->t{1,}

p{n,m}

p出现n到m次

tttt->t{1,5}

  • 单词字符是所有字母,数字和下划线。\w等同[a-z[A-Z][0-9]_]。\W等同于[^a-Za-z0-9]
  • p{n,}和p{n,m}中不能有空格,A{3, 6}(逗号和6有空格)
  • 可以使用小括号()来给模式分组,比如(ab)3->ababab,但是ab{3}->abbb

举个例子:QQ号的匹配是[1-9][0-9]{4,}。分析:qq号开头不能是0吧?所以[1-9]的意思是第一位为1到9的个位数,[0-9]{4,}的意思是剩下的是0到9的数字,但是至少有4位(qq号最少5位,此处4位+第一个1位)。
另外,有在线匹配正则表达式的网站,比如这个。可以测试你的正则表达式是否匹配,另外还有一些常用的正则表达式例子。

替换和分割字符串

使用String类的matches方法匹配正则表达式,如果能匹配那么返回true,反之为false。String类还包括repalceAll,replaceFirst,split方法,可以使用这些方法来替换和分割字符串。

System.out.println("Test Test Test".replaceAll("s\\w", "ok"));   //Teok Teok Teok
System.out.println("Test Test Test".replaceFirst("s\\w", "ok"));  //Teok Test Test

String[] test = "Test1test2TEST".split("\\d");
for(String t : test){
    System.out.println(t);
}				//Test test TEST

split方法后跟第二个参数(split(字符串, 匹配次数))用于确定模式匹配多少次。
另外,量词符默认都是贪婪的,就是说,如果要多次匹配(具体次数没有指定),那么默认是匹配最多次。可以再量词符后加?来使它变成匹配最少次。比如

System.out.println("Teeestt".replaceFirst("e+", "O"));  //Tostt
System.out.println("Teeestt".replaceFirst("e+?", "o")); //Toeestt

最后:正则表达式是一个很有用的工具,要熟练掌握还需要多加练习。