正則表達式
談起到正則表達式,很多開發人員都會感覺到又愛又恨,愛的是什麼呢?恨的又是什麼呢?愛的是正則表達式確實在開發當中非常有用,可以處理很多棘手的問題,
恨的是正則表達式確實很難理解,又很難記憶,更別說去自己使用正則表達式來解決實際當中的開發問題了。下面我來給大家分享一下,讓大家能夠輕鬆掌握正則表達式。
首先學習正則表達式,我們要知道爲什麼學習正則表達式,學習了對我們開發又有什麼好處?那麼讓我們來通過代碼直接給大家一個最好的解釋,上乾貨~
正則表達式的引入
需求:假設我們要對QQ號做驗證,驗證的規則是:
1.qq號必須是5-10位
2.數字0不可以作爲qq號碼的開頭
那麼我們來看看傳統的代碼編寫驗證:
public static boolean checkQQ(String qq) {
// 假設默認QQ號碼是符合規則的
boolean flag = true;
// 保證qq號碼必須5-10位
if (qq.length() >= 5 && qq.length() <= 10) {
// 保證不是數字0開頭
if (!qq.startsWith("0")) {
// 將字字符串轉換爲字符數組
char[] chs = qq.toCharArray();
// 遍歷字符數組
for (int i = 0; i < chs.length; i++) {
// 獲取到每一個字符
char c = chs[i];
// 保證是數字
if (!(c >= '0' && c <= '9')) {
// 如果不是數字,那麼標誌位值爲false
flag = false;
break;
}
}
} else {
// 如果是數字0開頭,那麼標誌位值爲false
flag = false;
}
} else {
// 如果不是5-10,那麼標誌位值爲false
flag = false;
}
return flag;
}
相信大家對上述代碼都能夠理解,但是大家應該也發現了使用傳統的if-else來校驗qq號碼,代碼非常冗餘,而且可讀性很差,何況才短短兩條規則就寫了這麼多的判斷,那真實的qq號碼肯定規則更多,如果讓你去驗證郵箱,或者網址呢?想想都覺得頭皮發麻有木有!!
那讓我們來看一看使用正則表達式之後的樣子
public static boolean checkQQByRegex(String qq) {
return qq.matches("[1-9][0-9]{4,9}");
}
怎麼樣,代碼很簡潔吧,那麼我們來測試一下看下是不是真的有效,
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("請輸入一個QQ號:");
String qq = input.next();
if (checkQQByRegex(qq)) {
System.out.println("合法QQ");
} else {
System.out.println("非法QQ");
}
}
代碼效果演示圖如下:
使用正則表達式和複雜的if-else能實現同樣的效果,但是正則表達式只寫了一行代碼,非常簡練,所以大家知道學習正則表達式的好處了吧!~
那麼讓我們來好好學習一下正則表達式吧!!!
正則表達式概述
概念: 使用單個字符串來描述/匹配一系列符合某個語法規則的字符串 "[1-9][0-9]{4,9}"匹配 993508067
在Java裏面來學習正則表達式的目的主要就是使用正則表達式來處理字符串複雜的 查找find/替換replace/匹配matches/分割split工作
使用步驟
1.通過大量的字符串找規律定義規則
2.使用這種規則去匹配新的字符串
3.匹配成功作出相應的操作(匹配 查找 替換 分割)
工具: https://regexper.com/
這個工具可謂是學習和編寫正則表達式的神器啊!給大家看看吧
下面就通過這個工具來介紹一下正則表達式的基本語法吧。
正則表達式由兩種基本字符組成
原義字符:字符本身就是一個正則表達式,例如 a, b, c ,\t ,\n ,\r ,\f等等
元字符: * + ? $ ^ () [] {}等等
對正則表達式進行分類
字符類:
[abc] 將字符進行歸類,可以出現[]中的其中一個 對abc其中一個進行匹配
[^abc] 對不是abc的字符進行匹配
範圍類:
[a-z] 表示代表a-z中的一個字符
表示所有的英文字母和數字 [a-zA-Z0-9]
預定義類:
\d == [0-9] 數字
\D == [^0-9] 非數字
空白字符:
[ \t\n\x0B\f\r] == \s space
[^ \t\n\x0B\f\r] == \S
[a-zA-Z0-9_] \w word
[^a-zA-Z0-9] \W
. 任何字符(與行結束符可能匹配也可能不匹配)
邊界字符
^:以XXX開頭
例如以a開頭 ^a
$:以XXX結尾
例如以b結尾 b$
\b:單詞邊界
\B:非單詞邊界
量詞
?:出現0次或者1次
a?
+:出現1次或者多次
a+
*:出現任意次
a*
{n}:出現正好n次
a{4}
{n,m}出現n-m次
a{2,6}
{n,}出現至少n次
分組 ()
如何讓Jack出現至少3次,而不是k出現三次
錯誤寫法 Jack{3,}
使用分組的正確寫法: (Jack){3,}
(Jack){3,}(?:love){2,}(work){3,}
忽略分組:
每一組能夠分組,但是沒有編號 ?:
或 |
Ja(ck|Love)Kitty
反向引用
利用分組的編號進行反向引用
反向引用使用$,必須先分組
將日期2018-04-27 轉換成爲 04/27/2018
String regex = "(\\d{4})-(\\d{2})-(\\d{2})";
String s = "2018-04-27";
System.out.println("原日期字符串:" + s);
String replace = s.replaceAll(regex, "$2/$3/$1");
System.out.println("使用正則修改後的日期字符串:" + replace);
效果圖演示如下:
正則表達式在Java中的應用
1.字符串查找操作 Pattern和Matcher
2.字符串匹配操作 字符串的matches()方法
3.字符串替換操作 字符串的replaceAll()和replaceFirst()方法
4.字符串分割 split() 方法
代碼示例
/*
* 驗證手機號
*
* 匹配如下四個手機號
* 18079243050
* 15160869850
* 18765068050
* 14235452850
*
* 找規則:
* 1.以1開頭
* 2.一共11位
* 3.50結尾
* 4.倒數第三位是 0 或者 8
*/
public class RegexDemo03 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("請輸入電話號碼:");
String mobileNumber = input.next();
checkMoblieNumber(mobileNumber);
System.out.println(checkMoblieNumber(mobileNumber));
}
public static boolean checkMoblieNumber(String mobileNumber) {
String regex = "^1\\d{7}[08](50)$";
return mobileNumber.matches(regex);
}
}
代碼示例2
/*
* He is a man
This is a boy
is that your car?
isn’t it?
What is your name?
將is替換替換成大寫的IS
*/
public class RegexDemo07 {
public static void main(String[] args) {
String s = "He is a man\r\n" +
"This is a boy\r\n" +
"is that your car?\r\n" +
"isn’t it?\r\n" +
"What is your name?";
System.out.println(replaceStr(s));
}
public static String replaceStr(String s) {
String regex = "\\bis\\b";
String result = s.replaceAll(regex, "IS");
return result;
}
}
運行結果如下圖所示:
代碼示例3
/*
統計文章中所有單詞出現的次數,每個單詞每個字符出現的次數,每個單詞的長度
* 統計下面這篇文章and,for,you,us出現個數並按照如下要求輸出
* 單詞(出現的次數)例如: and(x), for(y), us(m), you(z)
動態正則
動態sql
*/
public class Prictice12 {
public static void main(String[] args) {
String str = "On Friendship \r\n" +
"and a youth said, \"Speak to us of Friendship.\" \r\n" +
"\r\n" +
"Your friend is your needs answered. \r\n" +
"\r\n" +
"He is your field which you sow with love and reap with thanksgiving. \r\n" +
"\r\n" +
"and he is your board and your fireside. \r\n" +
"\r\n" +
"for you come to him with your hunger, and you seek him for peace. \r\n" +
"\r\n" +
"When your friend speaks his mind you fear not the \"nay\" in your own mind, nor do you withhold the \"ay.\" \r\n" +
"\r\n" +
"and when he is silent your heart ceases not to listen to his heart; \r\n" +
"\r\n" +
"for without words, in friendship, all thoughts, all desires, all expectations are born and shared, with joy that is unacclaimed.\r\n" +
"";
List<String> list = new ArrayList<String>();
String pattern = "\\b\\w+\\b";
Pattern p = Pattern.compile(pattern);
Matcher matcher = p.matcher(str);
while(matcher.find()) {
list.add(matcher.group());
}
Map<String, Integer> map = new TreeMap<String, Integer>();
for (String s: list) {
Integer num = map.get(s);
if(num == null) {
map.put(s, 1);
}else {
map.put(s, ++num);
}
}
// System.out.println(map);
StringBuilder sb = new StringBuilder();
sb.append("and(").append(map.get("and")).append(")for(").append(map.get("for"))
.append(")us(").append(map.get("us")).append(")you(").append(map.get("you")).append(")");
System.out.println(sb.toString());
}
}
效果演示如下圖所示: