今天帶大家瞭解一下Java當中的正則,依舊採用我自己 “”學習一個知識點的四部曲!“”
學習一個知識點的四部曲!
1.什麼是它(正則)?
2.用它(正則)有什麼好處? (這裏得拋磚引玉,先講沒有它會出現什麼問題,有了它解決了什麼問題)
突然想到了,先抑後揚,也叫欲揚先抑這種修辭手法
3.它主要包含哪些知識點(列出大綱)?
4.怎麼使用它?
一:什麼是它(正則)?
計算機科學的一個概念。正則表達式通常被用來檢索、替換那些符合某個模式(規則)的文本
Regular Expression,在代碼中常簡寫爲regex、regexp或RE
二:用它(正則)有什麼好處?
2.1沒他時
例子:可能你在前端驗證個郵箱,都得寫滿大屏幕的 if 代碼,有了正則之後,輕鬆搞定
2.2有他時
上述的問題,根本就不是問題,當然正則不止止這麼一點功能,上面只是舉一個例子
正則的作用主要是用來:查找,替換,匹配
三:它主要包含哪些知識點(列出大綱)?
3.1 元字符,量詞,方括號
3.2 介紹下Java中的正則對應的類 (Pattern 和 Matcher) 及其常用方法
3.3 String類中涉及正則的幾個方法
四:怎麼使用它?
關於怎麼使用它,其實就是把上面的含義都搞懂,把下面的練習都敲一遍就基本上入門了
量詞:
3.1.1元字符案列
package 字符串.原字符;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 正則的作用: 查找,替換,匹配
* 仔細一察覺,其實工作中經常用: 查找(Ctrl+F),替換(replace),搜索某些文件會用*匹配
*
* 演示一下: 元字符 和 量詞的用法
* @author wzj
*
*/
public class Demo {
public static void main(String[] args) {
/**
* 元字符:只能匹配單個字符
* . :表示任意的單個字符
* /d:digits(數字),匹配0~9中任意一個字符
* /s:space(空格), 匹配所有空白字符:如空格,製表符(\t),換行符,回車符等
* /w:word(單詞) a~zA~Z,0~9,_
*
* /D,/S,/W 大寫的都是表示非
* 例子: /D: 匹配非數字
*
*
* 量詞: 問嘉興, 是表示前面這個字符的次數,例子: a?,說明可以匹配 "空字符串" 和 "一個a的"的字符串
* ? : 0次或1次
* + : 1次或多次
* * : 0次或多次
* 這裏可以畫個三角形!
*/
//Pattern對象是正則表達式編譯完後在內存中的表現形式!!
Pattern p = Pattern.compile("\\d");
Matcher m = p.matcher("12");//只能匹配單個數字
System.out.println(m.matches());//fasle
//如果我想表示1個或多個數字呢?就得用量詞: ? + * (問嘉興)
boolean b2 = Pattern.compile("\\d+").matcher("2232323323").matches();
System.out.println(b2);//true,這樣的話就能匹配多個數字,這個正則除了出現數字,不能出現其他的
//如果只使用一次正則,就用這種方式
boolean b3 = Pattern.matches(".", "我的");
System.out.println(b3);//false, 只能匹配任意單個字符
boolean b4 = Pattern.matches(".*", "有點帥");
System.out.println(b4);//true
boolean b5 = Pattern.matches("ab?", "");
System.out.println(b5);//false, 注意:量詞只是匹配前一個字符的個數,這裏也就是b的次數
//如果想將ab表示成一個整體,得用()括起來
boolean b6 = Pattern.matches("(ab)?", "");
System.out.println(b6);//true,因爲?代表: 0次或1次
boolean b7 = Pattern.matches("\\w", "Z");
System.out.println(b7); //true,因爲\w匹配: a~z,A~Z(字母),0~9(數字),_(下劃線)
boolean b8 = Pattern.matches("\\D", "Z");
System.out.println(b8);//true,因爲\\D,匹配非數字
System.out.println(Pattern.matches(".", " ")); //. 可以匹配空格
}
}
3.1.2 量詞案列
package 字符串.原字符;
import java.util.regex.Pattern;
/**
* 量詞的用法:
* ?: 表示前面字符的0次或1次
* +: 表示前面字符的1次或多次
* *: 表示前面字符的0次或多次
* 帥{x},匹配包含x個“帥”的字符串
* 帥{x,y}: 匹配x或者y個“帥”的字符串
* 帥{x,}: 匹配至少x個“帥”的字符串
* 帥$: 匹配任何結尾爲“帥”的字符串,只能匹配單個字符!!
* ^帥: 匹配任何開頭爲“帥”的字符串,只能匹配單個字符!!
*
* 注意事項: 注意除了使用量詞,不然只能匹配單個字符!!!
* 可能沒有全部列全,但常見的就這些,用到頻率多的,可以以後自己再補充!!
* @author wzj
*
*/
public class Demo3 {
public static void main(String[] args) {
boolean b = Pattern.matches("我是大帥{1}比", "我是大帥比");
System.out.println(b);//true
//固定每天帥一次
boolean b2 = Pattern.matches("我是大帥{1}比", "我是大帥帥比");
System.out.println(b2);//false
//帥一次或者兩次
boolean b3 = Pattern.matches("我是大帥{1,2}比", "我是大帥帥比");
System.out.println(b3);//true
//需求:至少帥兩次
boolean b4 = Pattern.matches("我是大帥{2,}比", "我是大帥帥比");
System.out.println(b4);//true
boolean b5 = Pattern.matches("帥$", "有點帥");
System.out.println(b5);//false: 注意除了使用量詞,不然只能匹配單個字符!!!
// boolean b6 = Pattern.matches("*帥$", "有點帥");
// System.out.println(b6); //這個會報錯,我們說了量詞,是匹配前一個字符的次數,而這個*前面沒有字符!!所以報錯
boolean b7 = Pattern.matches("[^x00-xff]*帥$", "有點帥");
System.out.println(b7);//true, [^x00-xff]:是匹配中文的正則
// boolean b8 = Pattern.matches("[^x00-xff]", "d"); //false
boolean b8 = Pattern.matches("[^x00-xff]", "我的");
System.out.println(b8);//false, 也是隻能表示單個字符!!!
boolean b9 = Pattern.matches(".*帥$", "有點帥");
System.out.println(b9);//true, .代表任意單個字符!!
}
}
3.1.3 方括號
package 字符串.原字符;
import java.util.regex.Pattern;
/**
* 方括號:
* [abc]: 表示枚舉,表示a,b,c任意一個字符
* [^abc]: 表示非a,b,c的任意字符
* [0-9]: 表示0~9之間的任意字符
* [a-z]: 表示a~z之間的任意字符
* [A-Z]: 同理
* [red|blue|green]:查找任意指定的選項,和[abc]類似!
*
* @author wzj
*
*/
public class Demo2 {
public static void main(String[] args) {
boolean b = Pattern.matches("[abc]", "a");
System.out.println(b);//true, 表示只要滿足a,b,c中任意一個字符就行!
boolean b2 = Pattern.matches("[^abc]", "de");
System.out.println(b2);//false, 只能滿足非a,b,c的 “單個” 字符, 要想滿足多個得用量詞!!
boolean b3 = Pattern.matches("[^abc]+", "de");
System.out.println(b3);//true
boolean b4 = Pattern.matches("[^abc]+", "ad");
System.out.println(b4);//false, 這個+量詞,把前面[]中看成了一個整體,要麼存在單個非a,b,c 要麼多個!!
boolean b5 = Pattern.matches("[0-9]", "55");
System.out.println(b5);//false, 注意還是隻能匹配單個字符!!!
boolean b6 = Pattern.matches("[a-z]", "ab");
System.out.println(b6);//false,還是隻能匹配單個字符,匹配多個得用量詞: ? + *
boolean b7 = Pattern.matches("[蘋果|橘子|香蕉]", "橘子");
System.out.println(b7);//fasle, 注意:只能匹配單個字符!!
boolean b8 = Pattern.matches("(蘋果|橘子|香蕉)", "橘子");
System.out.println(b8);//true, 使用()纔是可以的
boolean b9 = Pattern.matches("[蘋果|橘子|香蕉]", "橘");
System.out.println(b9);//true
}
}
3.2 介紹下Java中的正則對應的類 (Pattern 和 Matcher) 及其常用方法
3.2.1
package 字符串.原字符;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 介紹一下Java中的正則表達式!!
* Pattern:模式
* Matches:匹配器
*/
public class Demo4 {
public static void main(String[] args) {
//Java中的正則,提供了Pattern和
//第一種寫法: Pattern對象是正則表達式編譯完後,在內存中的表現形式!!
Pattern p = Pattern.compile("^H\\d{2,}\\w{3}P$");
Matcher m = p.matcher("H123abcP");
System.out.println(m.matches());//true
Matcher m2 = m.reset("H123abcPW");//rest方法:可以將現有的Matcher對象應用於一個新的字符序列!
System.out.println(m2.matches());//false
//第二種寫法:可以使用鏈式編程的寫法
boolean b = Pattern.compile("^H\\d{2,}\\w{3}P$").matcher("H123abcP").matches();
System.out.println(b);//true
//第三種寫法: 如果某個正則表達式只用一次,那麼直接使用Pattern類中matches()靜態方法
boolean b2 = Pattern.matches("^H\\d{2,}\\w{3}P$", "H123abcP");
System.out.println(b2);//true
//第四種寫法
System.out.println("hello".matches("\\w+"));//true
}
}
3.2.2
package 字符串.原字符;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 介紹Matcher類中的一些常用方法
* @author wzj
*
*/
public class Demo6 {
public static void main(String[] args) {
/**
* 介紹一下matches方法和find方法
* matches:是全部匹配,字符串要完全對應正則的規則
* find:是部分匹配 ,字符串中的子串滿足就行,全部滿足還不行!!
*/
Pattern p1 = Pattern.compile("\\d");
Matcher m1 = p1.matcher("1");
System.out.println(m1.matches());//true :全部匹配: 跟equals方法作用類似
System.out.println(m1.find());//false :find方法是部分匹配,全部匹配還不行!!
Pattern p2 = Pattern.compile("\\d");
Matcher m2 = p2.matcher("12");
System.out.println(m2.matches());//false: 沒有完全匹配,因爲\\d只表示任意單個數字,而字符串是兩個
System.out.println(m2.find());//true: 部分匹配!
Matcher matcher = Pattern.compile("\\w").matcher("Java is very easy!");
while(matcher.find()) {//find():判斷目標字符串中是否包含與Pattern匹配的子串
System.out.print(matcher.group());//返回上一次和Pattern匹配的子串: 可以看出一般和find()一起使用,直接使用會報錯
}
//start和end方法主要用於確定子串在目標字符串中的位置
//創建一個Pattern對象,並用他建立一個Matcher對象
String destStr = "Java is Very easy!";
System.out.println("目標字符串:"+ destStr);
Matcher matcher2 = Pattern.compile("\\w+").matcher(destStr.trim()); //遇到空格就會結束
while(matcher2.find())
{
System.out.println(matcher2.group()+"\t子字符串的起始位置:"+matcher2.start()+"\t子串的結束位置:"+matcher2.end());
}
}
}
3.3 String類中涉及正則的幾個方法
package 字符串.原字符;
import java.util.Arrays;
/***
* String類中,涉及到正則的幾個方法
*
* boolean matches(String regex); 判斷該字符串是否匹配正則
* String replaceAll(String regex,String replacement);將字符串中匹配正則的子串替換後返回!!
* String replaceFirst(String regex,String replacement);將字符串中匹配正則的“首個子串”替換後返回!!
* String[] split(String regex); 根據正則拆分字符串,得到一個字符串數組!
* @author wzj
*
*/
public class Demo5 {
public static void main(String[] args) {
//1.matches用法!!
// testMatches();
//2.replaceAll用法!!
// testReplaceAll();用法!!
//3.replaceFirst
// testReplaceFirst();
//4.split();用法!!
testSplit();
}
private static void testSplit() {
String str = "hello , java";
String[] split = str.split(",");
System.out.println(Arrays.toString(split));
}
private static void testReplaceFirst() {
String str = "hello , java";
System.out.println(str.replaceFirst("\\w*", "♠"));//♠ , java:*遇到空格就停了
}
private static void testReplaceAll() {
String str = "我12愛的12我的12國家";
String newStr = str.replaceAll("\\d", "A");//將數字替換成A
System.out.println(newStr);
}
private static void testMatches() {
String str = "Hello World";
System.out.println(str.matches("^H"));//false,除了使用量詞,只能匹配單個字符!!
System.out.println(str.matches("^H\\w*"));//false, \w遇到空格就沒了
System.out.println(str.matches("^H\\w*\\s\\w*"));//true
}
}
練習:
package 字符串.練習;
import java.util.regex.Pattern;
//https://blog.csdn.net/qian_youyou/article/details/79121916
public class Demo1 {
public static void main(String[] args) {
//1.匹配整數的正則: 負整數,正整數,0
boolean b = Pattern.matches("\\d+", "0");
System.out.println(b);//這裏的正則是可以將0 和 正整數搞定
boolean b2 = Pattern.matches("-?\\d+", "-12");
System.out.println(b2);// 需要讓-可有可無, 所以用?搞定
//2.匹配非負整數的正則: 非負整數: 0 和 正整數!
boolean b3 = Pattern.matches("\\d+", "-1");
System.out.println(b3);
//3.匹配非正整數: 0 和 負整數
boolean b4 = Pattern.matches("[-\\d+|0]", "-1545");
System.out.println(b4);//fasle:[]裏面只能匹配單個字符,所以用量詞(?+*)作用不大!!
boolean b5 = Pattern.matches("[-\\d|0]", "-");
System.out.println(b5);//true: []:只能匹配單個字符: -, 多一個\\d就不匹配!!!
boolean b5_2 = Pattern.matches("[-\\d|0]", "-1");
System.out.println(b5_2);//fasle: 因爲[]只能匹配單個字,- 和 1 是兩個字符,所以不匹配!!!
boolean b6 = Pattern.matches("[我的|你]", "我的");
System.out.println(b6);//false: []裏面只能匹配單個字符,所以用量詞(?+*)作用不大!!
boolean b7 = Pattern.matches("(我的|你)", "我的");
System.out.println(b7);//true:
boolean b8 = Pattern.matches("(0|-\\d+)", "-65454");
System.out.println(b8);//ture: 表示0 或者 負整數
}
}
package 字符串.練習;
import java.util.regex.Pattern;
public class Demo2 {
public static void main(String[] args) {
//1.長度爲8-10的用戶密碼(以字母開頭、數字、下劃線)
boolean b = Pattern.matches("^[A-z]\\w{7,10}", "Z1272sdsd");
System.out.println(b);//true: [A-z]表示[a-zA-Z]中任意單個字符!!
//2.驗證輸入只能是漢字
boolean b2 = Pattern.matches("^[\\u4e00-\\u9fa5]{1,}$", "我");
System.out.println(b2);//true: 至少匹配一個漢字{1,}等價於+,沒看u4e00是什麼鬼
//3.電子郵箱驗證 itcast_wzj,[email protected], [email protected],可以滿足
boolean b3 = Pattern.matches("^\\w{7,10}@\\w{2,3}.(com|cn)", "[email protected]");
System.out.println(b3);
// ^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
boolean b4 = Pattern.matches("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$", "[email protected]");
System.out.println(b4);
System.out.println(Pattern.matches("([-+.]\\w+)*", ""));//true: 這個整可以是0 或者 是多個
System.out.println(Pattern.matches("([-+.]\\w+)*", "-dd-dd"));//true
System.out.println(Pattern.matches("([-+.]\\w+)*", "-dd-d"));//true??????????? //TODO
/**
* 這個正則挺好玩的
* 1.先看圓括號裏面的: [-+.]\\w+ 表示從-+.任意單個字符, 而\\w+ 表示一個或多個
* 例子: 滿足的字符串: -d 或 -ddd
* 2.然後看()*,圓括號把他們當成了一個整體, *表示0或多個
* 表示多個的例子: -d-d-d 或 -ddd-ddd-ddd
* 表示多個的例子: 空字符串即可滿足!!
*/
}
}
最後想說一下,學完之後找幾個題目練練手,不然不知道它的強大之處,正則其實是挺重要的,不要以爲我驗證一個郵箱,去網上一搜一大把,但有時候正則可以把你處理一些特殊的字符串需求,可以省了很多的代碼,我在公司就見過別人不用正則寫的一大把邏輯且繁瑣才解決問題,用了正則又方便,又簡潔,而且正則在java中會用到,JS中也會用到,linux下也會用到,就平時在eclipse中查找的時候,也會用到,把它學會何樂而不爲呢?
疑問:System.out.println(Pattern.matches("([-+.]\\w+)*", "-dd-d"));//true 這個爲什麼是true啊??
看到時候回過頭來,能不能解決!!
System.out.println(Pattern.matches("(-\\w+)*", "-dd-d"));
/**
* 我知道爲什麼是true了,因爲多了個+的原因
是把括號中看成一個整體
* 第一次. -\\w+: 可能是-dd
* 第二次. -\\w+: 可能是-d
* 然後*代表 0次 或 多次
*
* 之前的理解是先固定死()中的內容,然後看* :就是說假如()裏是 -a, 然後我再*,所以我就認爲,要麼-a不出現,要麼就是-a-a這樣的規律 出現!!
* 現在的理解就是:()中表達式能夠出現幾次!!!
*/
System.out.println(Pattern.matches("(-\\w)*", "-dd-d"));//fasle