Java的正則表達(dá)式深入分析
一.regex(正則表達(dá)式):RegularExpressions(代替了StringTokenizer);字符串處理利器;在unix流行,perl使用regex更牛。
主要用在字符串匹配、查找和替換。例如:匹配IP(范圍小于256)使用正則很好搞;從網(wǎng)頁(yè)中揪出大量email地址發(fā)送垃圾郵件;從網(wǎng)頁(yè)里揪出鏈接。包含Matcher(用模式匹配字符串后產(chǎn)生的結(jié)果)和pattern。
/*
* 告知此字符串是否匹配給定的正則表達(dá)式(也是一個(gè)字符串)。
*/
System.out.println("abc".matches("..."));//每個(gè)"."表示一個(gè)字符
/*
* 把字符串里的所有數(shù)字替換成"-",普通方法需要charAt逐個(gè)判斷;
* "\\d"表示任意一個(gè)數(shù)字或者換成"[0-9]";
* "\\D"表示任意一個(gè)非數(shù)字或者換成"[^0-9]"
*/
System.out.println("ab54564654sbg48746bshj".replaceAll("[0-9]", "-"));//每個(gè)"."表示一個(gè)字符
二、
/*
* compile將給定的正則表達(dá)式編譯到模式中(每次編譯需要費(fèi)時(shí)間);{3}表示恰好三次。
* X{n} X,恰好 n 次
* X{n,} X,至少 n 次
* X{n,m} X,至少 n 次,但是不超過 m 次
*/
Pattern p = Pattern.compile("[a-z]{3}");
Matcher m = p.matcher("ggs");//創(chuàng)建匹配給定輸入與此模式的匹配器。內(nèi)部實(shí)際上是創(chuàng)建了一個(gè)優(yōu)先狀態(tài)的自動(dòng)機(jī)(編譯原理)
//matcher和matches里待匹配的字符串實(shí)際上是CharSequence(接口),不過String實(shí)現(xiàn)了該接口,存在多態(tài)
System.out.println(m.matches());//若是"ggss"就不匹配了
//可一直接"ggs".matches("[a-z]{3}"),不過上面的有好處,至少效率高了,而且Pattern和Matcher提供了很多功能
三、在regex“. * +”中叫Meta Character;ctrl + shift + "/"表示注釋,換成"\"表示去掉注釋。
"a".matches(".");//true,"."表示任意一個(gè)字符,漢字也行
"aa".matches("aa");//true,也就是說(shuō)普通字符串也可以作為正則表達(dá)式
/*
* true,"*"表示0或者多個(gè)字符,不過后面的要和第一個(gè)相同,
* 否則false,也就是判斷字符串是否是單一字符組成的字符串
*/
"aaaa".matches("a*");
"".matches("a*");//true
"aaa".matches("a?");//true,一次或者0次
"".matches("a?");//true
"a".matches("a?");//true
"544848154564113".matches("\\d{3,100}");//true
//這個(gè)是最簡(jiǎn)單的IP判斷,不過若是超過255則判斷不出來(lái)
"192.168.0.aaa".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\d{1,3}");
"192".matches("[0-2][0-9][0-9]");
四、[abc]表示匹配任意一個(gè)字符;[^abc]表示出了abc以外的其他字母(必須還是字母,若是空串也返回false)字符;[a-zA-Z]等價(jià)于"[a-z]|[A-Z]"是否是某個(gè)大小寫字母;[A-Z&&[ABS]]表示大寫字母中取ABS中任一個(gè)。
//發(fā)現(xiàn)|和||沒區(qū)別,&和&&有區(qū)別,不知道這么理解對(duì)不對(duì)
System.out.println("C".matches("[A-Z&&[ABS]]"));//false
System.out.println("C".matches("[A-Z&[ABS]]"));//true
System.out.println("A".matches("[A-Z&&[ABS]]"));//true
System.out.println("A".matches("[A-Z&[ABS]]"));//true
System.out.println("C".matches("[A-Z|[ABS]]"));//true
System.out.println("C".matches("[A-Z||[ABS]]"));//true
五、\w 單詞字符:[a-zA-Z_0-9] 進(jìn)行用戶名匹配時(shí);\s 空白字符:[ \t\n\x0B\f\r]; \S 非空白字符:[^\s] ;\W 非單詞字符:[^\w] 。
" \n\t\r".matches("\\s{4}");//true
" ".matches("\\S");//false
"a_8".matches("\\w{3}");//true
//“+”表示一次或者多次
"abc888&^%".matches("[a-z]{1,3}\\d+[&^#%]+");//true
/*
* 待匹配字符也只是一個(gè)反斜線,不過不可寫成"\"那么和后面的"組合了,
* 前面的"無(wú)法匹配就會(huì)CE。
* 后面不可寫成"\\",那么會(huì)運(yùn)行錯(cuò)誤(編譯沒問題),必須寫成"\\\\"
*/
System.out.println("\\".matches("\\\\"));//true
六、POSIX 字符類(僅 US-ASCII)
\p{Lower} 小寫字母字符:[a-z] ;\p{Upper} 大寫字母字符:[A-Z] ;\p{ASCII} 所有 ASCII:[\x00-\x7F] ;\p{Alpha} 字母字符:[\p{Lower}\p{Upper}] ;\p{Digit} 十進(jìn)制數(shù)字:[0-9] 。
七、邊界匹配器
^ 行的開頭
$ 行的結(jié)尾
\b 單詞邊界
\B 非單詞邊界
\A 輸入的開頭
\G 上一個(gè)匹配的結(jié)尾
\Z 輸入的結(jié)尾,僅用于最后的結(jié)束符(如果有的話)
\z 輸入的結(jié)尾
"hello world".matches("^h.*");//^行的開頭
"hello world".matches(".*ld$");//$行的結(jié)尾
"hello world".matches("^h[a-z]{1,3}o\\b.*");//\b單詞邊界
"helloworld".matches("^h[a-z]{1,3}o\\b.*");
" \n".matches("^[\\s&&[^\\n]]*\\n$");//判斷空白行,空白行開頭是空白符
八、還可以在find方法下使用m.start()和m.end()返回開始位置和結(jié)束位置的下一個(gè);若是找不到則出錯(cuò)。
Pattern p = Pattern.compile("\\d{3,5}");
String s = "133-34444-333-00";
Matcher m = p.matcher(s);
m.matches();//matches匹配全部字符串
m.reset();
/*
* 下面若是先調(diào)用了reset方法則輸出true,true,true,false.
* 否則倒數(shù)第二個(gè)find也輸出false。
* 原因如下:
* matches匹配到第一個(gè)"-"發(fā)現(xiàn)不匹配了,但是這四個(gè)字符已經(jīng)被吃掉啦,再次匹配就從
* 34444開始了,第二個(gè)find從333,因?yàn)閒ind匹配的是下一個(gè)子序列。
* reset方法讓matches吃掉的字符串再吐出來(lái)。
* 綜上:matches和find之間要使用reset,因?yàn)槎呦嗷ビ绊?BR> *
*/
m.find();
m.find();
m.find();//嘗試查找與該模式匹配的輸入序列的下一個(gè)子序列
m.find();
/*
* 嘗試將從區(qū)域開頭開始的輸入序列與該模式匹配。
* Thinking in java的作者狠狠滴批評(píng)了這個(gè)方法,因?yàn)閺淖置婵床怀鰜?lái)到底從哪開始匹配。
* 下面全部是true,因?yàn)槊看味紡念^開始
*/
m.lookingAt();
m.lookingAt();
m.lookingAt();
m.lookingAt();
九、字符串替換
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class TestRegexReplacement {
public static void main(String[] args) {
Pattern p = Pattern.compile("java",Pattern.CASE_INSENSITIVE);//后面的參數(shù)是整形,表示“大小寫不敏感”
Matcher m = p.matcher("Java java hxsyl Ilovejava java JaVaAcmer");
while(m.find()) {
System.out.println(m.group());//m.group會(huì)輸出所有的java(忽略大小寫)
}
String s = m.replaceAll("Java");//String也有該方法
System.out.println(s);
m.reset();//一定要加,因?yàn)閒ind和matcher相互影響
StringBuffer sb = new StringBuffer();
int i = 0;
/*
* 下面的方法是把找到的奇數(shù)個(gè)java替換為“Java”,偶數(shù)個(gè)替換成"java"
*/
while(m.find()) {
i++;
//不能直接寫成i&1必須轉(zhuǎn)化為boolean
if((i&1)==1) {
m.appendReplacement(sb, "Java");
}else {
m.appendReplacement(sb, "java");
}
}
m.appendTail(sb);//把找到的最后一個(gè)java后邊的剩余字符串加上
System.out.println(sb);//不加reset的話只輸出了Acmer
}
}
十、分組
/*
* 分別加上小括號(hào),不算最外邊的大括號(hào),第一個(gè)左括號(hào)便是第一組
*/
Pattern p = Pattern.compile("(\\d{3,5})([a-z]{2})");
String s = "123aaa-77878bb-646dd-00";
Matcher m = p.matcher(s);
while(m.find()) {
System.out.println(m.group());
System.out.println(m.group(1));//輸出每對(duì)符合的 數(shù)字
System.out.println(m.group(2));//輸出每對(duì)符合的 字母
}
十一、抓取網(wǎng)頁(yè)中的email
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*
* 需要什么養(yǎng)的方法的話先些方法名
* 然后ctrl + 1列出推薦,系統(tǒng)創(chuàng)建該方法
*/
public class EmailSpider {
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
BufferedReader br = new BufferedReader(new FileReader("F:\\regex.html"));
String line = "";
try {
while((line=br.readLine())!=null) {
solve(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void solve(String line) {
// TODO Auto-generated method stub
//正則表達(dá)式要是不滿足相應(yīng)功能的話不會(huì)出錯(cuò),因?yàn)樗亲址?BR> Pattern p = Pattern.compile("[\\w[.-]]+@[\\w[.-]]+\\.[\\w]+");
Matcher m = p.matcher(line);
while(m.find()) {
System.out.println(m.group());
}
}
}
十二、代碼統(tǒng)計(jì)
View Code
/*
* 統(tǒng)計(jì)代碼里多少空行,注釋行,程序行
* 實(shí)際上使用String里的startsWith和endsWith也行.
* 若是項(xiàng)目經(jīng)理用的話還要統(tǒng)計(jì)每行的字符數(shù)是否以{;結(jié)尾,防止偷懶
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class CoderCount {
static long normalLines = 0;
static long commentLines = 0;
static long whiteLines = 0;
public static void main(String[] args) {
File f = new File("D:\\share\\src");
File[] codeFiles = f.listFiles();
for(File child : codeFiles){
if(child.getName().matches(".*\\.java$")) {
solve(child);
}
}
System.out.println("normalLines:" + normalLines);
System.out.println("commentLines:" + commentLines);
System.out.println("whiteLines:" + whiteLines);
}
private static void solve(File f) {
BufferedReader br = null;
boolean comment = false;
try {
br = new BufferedReader(new FileReader(f));
String line = "";
while((line = br.readLine()) != null) {
/*
* //有的注釋行前面有一個(gè)tab
* 不可寫在readLine后
* 最后一行的話會(huì)空指針
*/
line = line.trim();
//readLine讀出字符串后就把后面的換行去掉啦
if(line.matches("^[\\s&&[^\\n]]*$")) {
whiteLines ++;
} else if (line.startsWith("/*") && !line.endsWith("*/")) {
commentLines ++;
comment = true;
} else if (line.startsWith("/*") && line.endsWith("*/")) {
commentLines ++;
} else if (true == comment) {
commentLines ++;
if(line.endsWith("*/")) {
comment = false;
}
} else if (line.startsWith("http://")) {
commentLines ++;
} else {
normalLines ++;
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(br != null) {
try {
br.close();
br = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
十三、Quantifiers
包括?*+;默認(rèn)全是Greedy,還有Reluctant和Possessive(獨(dú)占性的)。
//加上分組是為了看得更清晰一些
Pattern p = Pattern.compile("(.{3,10})+[0-9]");
String s = "aaaa5bbbb6";//長(zhǎng)度是10
Matcher m = p.matcher(s);
/*
* 現(xiàn)在輸出0-10,默認(rèn)是Greedy,先吞進(jìn)10個(gè)字符,發(fā)現(xiàn)不匹配,吐出來(lái)一個(gè),發(fā)現(xiàn)匹配了;
* 若是Pattern.compile("(.{3,10}?)+[0-9]")則成了Reluctant,那么是先吞進(jìn)三個(gè)字符,發(fā)現(xiàn)不匹配,繼續(xù)吞入 知道匹配,輸出0到5;
* 若是Pattern.compile("(.{3,10}++)+[0-9]")則是Possessive(獨(dú)占式),也是先吞入10個(gè)字符,但是不向外吐,那么就不匹配了,
* 這種方式主要用在需要高效率的地方(會(huì)有誤差)。
*/
if(m.find()) {
System.out.println(m.start() + "----" + m.end());
}else {
System.put.println("Not match!");
}
十四、補(bǔ)充(非捕獲組)
//非捕獲組的意思和字面相反,意思是若是符合則捕獲
Pattern p = Pattern.compile("(?=a).{3}");
/*
* 輸出a66,相當(dāng)于要求以a開頭,也可以這么寫Pattern.compile("[a].{2}");
* 若是Pattern.compile(".{3}(?!=a)")不是不以a結(jié)尾{2}[^a],而是下一個(gè)字符不是a(lookahead),輸出44a,66b,所以這種用法不常用;
* 若是Pattern.compile(".{3}(?=a)")則輸出444(因?yàn)?=a是lookahead),放在前面則包含在組內(nèi),后面則不包含在組內(nèi);
*
*
*/
String s = "444a66b";
Matcher m = p.matcher(s);
while(m.find()) {
System.out.println(m.group());
}
十五、Back Reference
Pattern p = Pattern.compile("(\\d\\d)\\1");
/*
* 輸出true,\\1表示和第一個(gè)組的一樣,若改成1213就不對(duì)了;
* 若是Pattern.compile("(\\d(\\d))\\2")則需改成122才對(duì)
*
*/
String s = "1212";
Matcher m = p.matcher(s);
System.out.println(m.matches());
十六、flags的簡(jiǎn)寫
"."是不匹配換行的,記住CASE_INSENSITIVE就行了,簡(jiǎn)寫“通過嵌入式標(biāo)志表達(dá)式 (?i) 也可以啟用不區(qū)分大小寫的匹配”。
- java正則表達(dá)式驗(yàn)證郵箱、電話號(hào)碼示例
- java正則表達(dá)式使用示例
- JavaScript表單通過正則表達(dá)式驗(yàn)證電話號(hào)碼
- JavaScript通過正則表達(dá)式實(shí)現(xiàn)表單驗(yàn)證電話號(hào)碼
- java正則表達(dá)式解析html示例分享
- java正則表達(dá)式獲取url的host示例
- java正則表達(dá)式提取數(shù)字的方法實(shí)例
- 常用的JavaScript驗(yàn)證正則表達(dá)式匯總
- javascipt匹配單行和多行注釋的正則表達(dá)式
- 利用Java正則表達(dá)式校驗(yàn)郵箱與手機(jī)號(hào)
- 正則表達(dá)式語(yǔ)法規(guī)則及在Javascript和C#中的使用方法
- javascript正則表達(dá)式容易被忽略的小問題整理
- 如何使用Javascript正則表達(dá)式來(lái)格式化XML內(nèi)容
- java正則表達(dá)式簡(jiǎn)單使用和網(wǎng)頁(yè)爬蟲的制作代碼
- 如何使用JavaScript和正則表達(dá)式進(jìn)行數(shù)據(jù)驗(yàn)證
- javascript中使用正則表達(dá)式進(jìn)行字符串驗(yàn)證示例
- java中 利用正則表達(dá)式提取( )內(nèi)內(nèi)容
- java正則表達(dá)式匹配網(wǎng)頁(yè)所有網(wǎng)址和鏈接文字的示例
相關(guān)文章
IDEA安裝阿里巴巴編碼規(guī)范插件的兩種方式詳解(在線安裝和離線安裝)
這篇文章主要介紹了IDEA安裝阿里巴巴編碼規(guī)范插件的兩種方式詳解(在線安裝和離線安裝),本文通過截圖給大家展示的非常詳細(xì),需要的朋友可以參考下2021-09-09
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(20)
下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧,希望可以幫到你2021-07-07
SSH框架網(wǎng)上商城項(xiàng)目第13戰(zhàn)之Struts2文件上傳功能
這篇文章主要為大家詳細(xì)介紹了SSH框架網(wǎng)上商城項(xiàng)目第13戰(zhàn)之Struts2文件上傳功能的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-06-06
基于Java文件輸入輸出流實(shí)現(xiàn)文件上傳下載功能
這篇文章主要為大家詳細(xì)介紹了基于Java文件輸入輸出流實(shí)現(xiàn)文件上傳下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
Java基于Rest?Assured自動(dòng)化測(cè)試接口詳解
Rest Assured 是一個(gè)基于 Java 的流行的用于測(cè)試 RESTful API 的庫(kù)。這篇文章主要介紹了Java如何基于Rest?Assured實(shí)現(xiàn)自動(dòng)化測(cè)試接口,需要的可以參考一下2023-03-03
基于JDK8-lambda表達(dá)式四種forEach性能對(duì)比
這篇文章主要介紹了基于JDK8-lambda表達(dá)式四種forEach性能對(duì)比,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
HttpClient實(shí)現(xiàn)表單提交上傳文件
這篇文章主要為大家詳細(xì)介紹了HttpClient實(shí)現(xiàn)表單提交上傳文件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
idea搭建可運(yùn)行Servlet的Web項(xiàng)目
在網(wǎng)上看到一篇很詳細(xì)的 intelliJ IDEA 創(chuàng)建web項(xiàng)目并簡(jiǎn)單部署servlet的圖文教程,今天自己也配置一下,留個(gè)筆記,感興趣的可以了解一下2021-06-06
詳談@Cacheable不起作用的原因:bean未序列化問題
這篇文章主要介紹了@Cacheable不起作用的原因:bean未序列化問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01

