一、概述
1、正則表達式的概念:符合一定規則的表達式2、正則表達式的作用:用於專門操作字符串。
3、正則表達式的特點:用一些特定的符號來表示一些代碼操作,這樣可以簡化書寫。
4、正則表達式的利弊
好處:可以簡化對字符串的複雜操作
弊端:符號定義越多,正則越長,閱讀性越差
5、爲什麼要引入正則表達式呢?
二、常用的正則表達式規則
1、字符
x | 字符x |
\\ | 反斜線字符 |
\On | 帶有八進制值 0 的字符 n (0 <= n <= 7) |
\Onn | 帶有八進制值 0 的字符 nn (0 <= n <= 7) |
\Omnn | 帶有八進制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7) |
\xhh | 帶有十六進制值 0x 的字符 hh |
\uhhhh | 帶有十六進制值 0x 的字符 hhhh |
\t | 製表符 ('\u0009') |
\n | 新行(換行)符 ('\u000A') |
\r | 回車符 ('\u000D') |
\f | 換頁符 ('\u000C') |
\a | 報警 (bell) 符 ('\u0007') |
\e | 轉義符 ('\u001B') |
\cx | 對應於 x 的控制符 |
2、字符類
[abc] | a、b 或 c(簡單類) |
[^abc] | 任何字符,除了 a、b 或 c(否定) |
[a-zA-Z] | a 到 z 或 A 到 Z,兩頭的字母包括在內(範圍) |
[a-d[m-p]] | a 到 d 或 m 到 p:[a-dm-p](並集) |
[a-z&&[def]] | d、e 或 f(交集) |
[a-z&&[^bc]] | a 到 z,除了 b 和 c:[ad-z](減去) |
[a-z&&[^m-p]] | a 到 z,而非 m 到 p:[a-lq-z](減去) |
3、預定義字符類
. | 任何字符(與行結束符可能匹配也可能不匹配) |
\d | 數字:[0-9] |
\D | 非數字: [^0-9] |
\s | 非數字: [^0-9] |
\S | 非空白字符:[^\s] |
\w | 單詞字符:[a-zA-Z_0-9] |
\W | 非單詞字符:[^\w] |
4、邊界匹配器
^ | 行的開頭 |
$ | 行的結尾 |
\b | 單詞邊界 |
\B | 非單詞邊界 |
\A | 輸入的開頭 |
\G | 上一個匹配的結尾 |
\Z | 輸入的結尾,僅用於最後的結束符(如果有的話) |
\z | 輸入的結尾 |
5、greedy數量詞
X? | X,一次或一次也沒有 |
X* | X,零次或多次 |
X+ | X,一次或多次 |
X{n} | X,恰好 n 次 |
X{n,} | X,至少 n 次 |
X{n,m} | X,至少 n 次,但是不超過 m 次 |
6、組和捕獲
捕獲組可以通過從左到右計算其開括號來編號。例如,在表達式 ((A)(B(C))) 中,存在四個這樣的組:a)、((A)(B(C)))
b)、\A
c)、(B(C))
d)、(C)
之所以這樣命名捕獲組是因爲在匹配中,保存了與這些組匹配的輸入序列的每個子序列。捕獲的子序列稍後可以通過 Back 引用在表達式中使用,也可以在匹配操作完成後從匹配器獲取。
三、具體操作功能
1、匹配
matches(String regex)
:用規則匹配整個字符串,只要有一處不符合規則。就返回false。如下代碼所示:
public class RegexTest1{
/*
需求:對手機號碼進行匹配
分析:手機號碼段13xxxxxxx,15xxxxx,18xxxxxxx
*/
public static void main(String[] args){
String tel = "16900001111";
//定義電話號碼規則
String telReg = "1[358]\\d{9}";
System.out.println(tel.matches(telReg));//結果:false
}
}
2、切割
split(String regex)
:根據給定正則表達式的匹配拆分此字符串。split(String regex, int limit)
:根據匹配給定的正則表達式來拆分此字符串。如下代碼所示:
public class RegexTest2{
public static void main(String[] args){
String str = "erkktyqqquizzzzzo";
/*
按照疊詞完成切割。爲了可以讓規則的結果被重用
可以將規則封裝成一個組。用()完成。組的出現都有編號。
從1開始。 想要使用已有的組可以通過 \n(n就是組的編號)的形式來獲取
*/
String reg = "(.)\\1+";
String[] arr = str.split(reg);
System.out.println(arr.length);
for(String s : arr)
{
System.out.println(s);
}
}
}
3、替換
replaceAll(String regex,String replacement)
:使用給定的
replacement 替換此字符串所有匹配給定的正則表達式的子字符串。replaceFirst(String regex,String replacement)
:使用給定的
replacement 替換此字符串匹配給定的正則表達式的第一個子字符串。如下代碼所示:
public class RegexTest3{
public static void main(String[] args){
String str = "erkktyqqquizzzzzo";
//正則規則
String regex = "(.)\\1+";
str = str.replaceAll(regex,"$1");//$1將重疊的字符替換成單個字母。
System.out.println(str);//erktyquizo
}
}
4、獲取
將字符串中符合規則的子串取出。操作步驟:
①將正則表達式封裝成對象
②讓正則對象與要操作的字符串相關聯
③關聯後,獲取正則匹配引擎
④通過引擎對符合規則的子串進行操作,例如查找find(),取出group()
如下代碼所示:
import java.util.regex.*;
class RegexTest4
{
public static void main(String[] args)
{
getDemo();
}
public static void getDemo()
{
String str = "ming tian jiu yao fang jia le ,da jia。";
System.out.println(str);
String reg = "\\b[a-z]{4}\\b";
//將規則封裝成對象。
Pattern p = Pattern.compile(reg);
//讓正則對象和要作用的字符串相關聯。獲取匹配器對象。
Matcher m = p.matcher(str);
/*
//其實String類中的matches方法。用的就是Pattern和Matcher對象來完成的。
//只不過被String的方法封裝後,用起來較爲簡單。但是功能卻單一。
System.out.println(m.matches());
boolean b = m.find();//將規則作用到字符串上,並進行符合規則的子串查找。
System.out.println(b);
System.out.println(m.group());//用於獲取匹配後結果。
System.out.println("matches:"+m.matches()); */
while(m.find())
{
System.out.println(m.group());
System.out.println(m.start()+"...."+m.end());
}
}
}
5、四種功能的選擇
這四種功能,具體的得按照我們的需求來選擇,如:- 如果我們只需要指導該字符串是否符合我們的標準,則只需要使用匹配。
- 如果我們想要將字符串中的某子串變成另一個子串,則使用替換。
- 如果我們想要將一個字符串按照我們的要求變成多個字符串,則使用切割。
- 如果想要獲取符合我們需求的子串,則使用獲取。
- 當然,在將字符串變成符合我們需求的過程中,某些功能可能需要反覆的使用才能達到目標。
四、正則表達式小練習
1、正則表達式小練習一:/*
需求:
將下列字符串轉成:我要學編程.
到底用四種功能中的哪一個呢?或者哪幾個呢?
思路方式:
1,如果只想知道該字符是否對是錯,使用匹配。
2,想要將已有的字符串變成另一個字符串,替換。
3,想要按照自定的方式將字符串變成多個字符串。切割。獲取規則以外的子串。
4,想要拿到符合需求的字符串子串,獲取。獲取符合規則的子串。
*/
class RegexTest5
{
public static void main(String[] args) {
String str = "我我...我我...我要..要要...要要...學學學....學學...編編編...編程..程.程程...程...程";
//去除文字段中的.
str = str.replaceAll("\\.+","");
System.out.println(str);//我我我我我要要要要要學學學學學編編編編程程程程程程
//將多個重複的內容變成單個內容
str = str.replaceAll("(.)\\1+","$1");
System.out.println(str);//我要學編程
}
}
2、正則表達式小練習二:將ip地址進行地址段順序的排序。import java.util.*;
public class RegexTest6{
/*
將ip地址進行地址段順序的排序。
還按照字符串自然順序,只要讓它們每一段都是3位即可。
1,按照每一段需要的最多的0進行補齊,那麼每一段就會至少保證有3位。
2,將每一段只保留3位。這樣,所有的ip地址都是每一段3位。
*/
public static void main(String[] args){
String ip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";
//將每一段需要的最多的0補齊
ip = ip.replaceAll("(\\d+)","00$1");
System.out.println(ip);
//去掉有些段前面多餘的0,保證每一段都是三位。
ip = ip.replaceAll("0*(\\d{3})","$1");
System.out.println(ip);
//將ip按照空格進行切割,並存入數組。
String[] arr = ip.split(" ");
//定義一個TreeSet集合,進行自然順序排序。。
TreeSet<String> ts = new TreeSet<String>();
//將數組中的元素添加進集合
for(String s : arr)
{
ts.add(s);
}
//打印進行排序後的集合中的元素
for(String s : ts)
{
System.out.println(s.replaceAll("0*(\\d+)","$1"));
}
/*
2.2.2.2
8.109.90.30
10.10.10.10
102.49.23.13
192.68.1.254
*/
}
}
3、正則表達式小練習三:網絡爬蟲/*
網絡爬蟲(蜘蛛)
實際上是一個功能,用於蒐集網絡上的指定信息
需求:可用於收集郵箱,qq號等之類的信息。
應用:如通過關鍵字搜索blog,實際就是使用的“蜘蛛”,通過查找關鍵字獲取相關的blog
*/
import java.net.*;
import java.util.regex.*;
import java.io.*;
class RegexTest7
{
public static void main(String[] args)throws Exception
{
//getFileMail();
getWebMail();
}
//獲取網頁中mail
public static void getWebMail()throws Exception
{
//封裝網頁地址
URL url=new URL("http://tieba.baidu.com/p/1390896758");
//連接服務器
URLConnection conn=url.openConnection();
//帶緩衝區的網頁讀取流
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line=null;
//定義匹配郵件地址的正則表達式
String regex="\\w+@\\w+(\\.\\w+)+";
Pattern p=Pattern.compile(regex);//封裝正則表達式
//讀取網頁數據
while ((line=br.readLine())!=null)
{
//正則關聯數據
Matcher m=p.matcher(line);
//尋找匹配郵箱
while (m.find())
{
System.out.println(m.group());//輸出匹配郵箱
}
}
}
//獲取指定文檔中的郵件地址。使用獲取功能。Pattern Matcher
public static void getFileMail()throws Exception
{
//將文件封裝成對象
File file=new File("E:\\Java Study\\Practice\\day25\\mail.txt");
//創建帶緩衝區的讀取流
BufferedReader br=new BufferedReader(new FileReader(file));
String line=null;
//定義正則表達式
String regex="\\w+@[a-zA-Z]+(\\.[a-zA-z]+)+";
//創建Pattern對象,封裝正則表達式
Pattern p=Pattern.compile(regex);
//讀取文件中數據
while ((line=br.readLine())!=null)
{
//關流字符串
Matcher m=p.matcher(line);
while (m.find())//尋找匹配的字符串
{
System.out.println(m.group());//輸出匹配的字符串
}
}
}
}