——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
一、正则表达式基础
(1)、什么是正则表达式?
是一种强大而灵活的文本处理工具,在java的Unix工具集之中。
(2)、正则表达式有什么作用?
用于一些特定的符号来表示一些代码操作,进而操作字符串。可以简化对字符串的操作。
(3)、主要的四种具体功能:匹配、切割、替换和获取
匹配 返回的是真假;
切割 是把规则以外的取出来
替换 是把替换后的取出来
获取 是把规则以内的取出来
(4)、常见的正则表达式符号:
说明:X表示字符X或者匹配的规则。
1、字符
x 字符 x
\ 反斜线字符
\t 制表符 (‘\u0009’)
\n 新行(换行)符 (‘\u000A’)
\r 回车符 (‘\u000D’)
\f 换页符 (‘\u000C’)
\a 报警 (bell) 符 (‘\u0007’)
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 空白字符:[ \t\n\x0B\f\r]
\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、组
组是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为0表示整个表达式,组号1表示被第一对括号括起来的组,以此类推。因此,在下面这个表达式:
A(B(C))D中有三个组,组0是ABCD,组1是BC,组2是C.
二、正则表达式功能的具体应用
(1)正则表达式匹配的应用
注意:
①\d表示的是数字[0-9],但是在正则表达式中反斜杠“\”必须是成对出现如“\d”
②匹配:String matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。
例子:
/*
匹配
例子1:
手机号段只有 13xxx 15xxx 18xxxx
*/
public static void checkTel()
{
String tel = "16900001111";
String telReg = "1[358]\\d{9}";
System.out.println(tel.matches(telReg));
}
/*
例子2:字符串"b23a23456789"用正则表达式"[a-zA-Z]\\d*"匹配,检验是否满足要求
*/
public static void demo()
{
String str = "b23a23456789";
String reg = "[a-zA-Z]\\d*";
boolean b= str.matches(reg);
System.out.println(b);
}
/*
例子3:对QQ号码进行校验
要求:5~15 0不能开头,只能是数字
*/
public static void checkQQ()
{
String qq = "123a454";
String regex = "[1-9]\\d{4,14}";
boolean flag = qq.matches(regex);
if(flag)
System.out.println(qq+"...is ok");
else
System.out.println(qq+"... 不合法");
}
(2)正则表达式切割的应用
注意:
切割:String类中的String[]split(String regex)方法
它的主要格式:String str = “”;
String reg =”“;
String[] arr = str.split(reg);
例子:
/*
例子1、把字符串用正则表达式的各种方式切割
*/
class SplitDemo
{
public static void main(String[] args)
{
String regex1="\\.";//按 .切
String regex2=" +";//按空格切,可能有一个空格或者多个空格
String regex3="(.)\\1+";//按照出现两次或者以上的叠词切
String[] arr="13.56.24.56.87".split(regex1);//按 . 切
print(arr);
arr ="haha hrhr jrkkc ksdfs dfs fdsd ".split(regex2);//按空格切
print(arr);
arr="hhjdjajjjjdfhgggdfsdjj".split(regex3);//按叠词切
print(arr);
}
(3)正则表达式替代的应用
注意:替换:String replaceAll(regex,str); 如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组。
例子:
String str = "wer138998000000ty1234564uiod234345675f";//将字符串中的数组替换成#。
replaceAllDemo(str,"\\d{5,}","#");
String str1 = "erkktyqqquizzzzzo";//将叠词替换成$. //将重叠的字符替换成单个字母。zzzz->z
replaceAllDemo(str1,"(.)\\1+","$1");
(4)、正则表达式获取的应用
注意:匹配就是把字符串中符合规则的部分取出来,常见的网络爬虫技术。
用匹配的格式和思路:
String str = “wo shi duan huang jun “;
String reg = “”;
第一步:将正则表达式封装成对象
Pattern p =Pattern.compile(reg);
第二步:让正则对象和要操作的字符串相关联,获取匹配器对象。
Matcher m =p.Matcher(str);
第三步:关联后,获取正则匹配引擎
第四步:通过引擎对符合规则的子串进行操作,比如取出
例子:
*/
import java.util.regex.*;
class RegexDemo2
{
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);
//boolean b = m.find();//将规则作用到字符串上,并进行符合规则的子串查找。
//System.out.println(b);
//System.out.println(m.group());//用于获取匹配后结果。
while(m.find()) //用循环获取所有的匹配结果
{
System.out.println(m.group());
System.out.println(m.start()+"...."+m.end());
//start()和end()分别表示匹配字符的开始和结尾的索引
}
}
}
三、正则表达式深入
1、正则表达式与java I/O
到目前为止,你看到的都是用正则表达式处理静态字符串的例子。下面我们来演示一下怎样用正则表达式扫描文件并且找出匹配的字符串。受Unix的grep启发,我写了个JGrep.java,它需要两个参数:文件名,以及匹配字符串用的正则表达式。它会把匹配这个正则表达式那部分内容及其所属行的行号打印出来。
//: c12:JGrep.java
// A very simple version of the "grep" program.
// {Args: JGrep.java "//b[Ssct]//w+"}
import java.io.*;
import java.util.regex.*;
import java.util.*;
import com.bruceeckel.util.*;
public class JGrep {
&nbsnbsp;p = Pattern.compile(args[1]);
// Iterate through the lines of the input file:
ListIterator it = new TextFile(args[0]).listIterator();
while(it.hasNext()) {
Matcher m = p.matcher((String)it.next());
while> // Iterate through the lines of the input file:
ListIterator it = new TextFile(args[0]).listIterator();
while(it.hasNext()) {
Matcher m = p.matcher((String)it.next());
while(m.find())
System.out.println(it.nextIndex() + ": " +
m.group() + ": " + m.start());
}
}
} ///:~
2、Scanner定界符与使用正则表达式扫描
import java.util.Scanner;
import java.util.regex.MatchResult;
/**
* @author clydelou
*
*/
public class ScannerDelimiter {
/**
* @param args
*/
static String threatData = "58.27.82.161@02/10/2005/n"
+ "204.45.234.40@02/11/2005/n" + "58.27.82.161@02/11/2005/n"
+ "58.27.82.161@02/12/2005/n" + "58.27.82.161@02/13/2005/n"
+ "[next log section with different data format]";
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scanner = new Scanner("12, 42,78,99,42");// 默认情况下,Scanner根据空白字符对输入进行分词,但是你可以用正则表达式指定自己所需的定界符
scanner.useDelimiter("//s*,//s*");// 使用逗号(包括逗号前后任意的空白字符)作为定界符
System.out.println(scanner.delimiter());// 使用delimiter()方法用来返回当前正在作为定界符的Pattern对象
while (scanner.hasNextInt())
System.out.print(scanner.nextInt() + "/t");
System.out.println();
// 使用正则表达式扫描
// 当next()方法配合指定的正则表达式使用时,将找到下一个匹配该模式的输入部分,调用match()方法就可以获得匹配结果.
// 注意:在配合正则表达式使用扫描时,它仅仅针对下一个输入分词进行匹配,如果正则表达式中含有界定符,那永远都不可能匹配成功.
scanner = new Scanner(threatData);
String pattern = "(//d+[.]//d+[.]+//d+[.]//d+)@"
+ "(//d{2}///d{2}///d{4})";
四、正则表达式必须掌握的基础例子
(1)工作中经常用到IP地址用正则表达式进行处理
/*
需求:
将ip地址进行地址段顺序的排序。
192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.301
思路:
还按照字符串自然顺序,只要让他们每一段都是3位即可。
1、按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位。
2、将每一段只保留3位。这样,所有的ip地址都是每一段3位。
*/
import java.util.*;
class IPSortTest
{
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.301";
System.out.println(ip);
String regex="(\\d+)";
ip=ip.replaceAll(regex,"00$1");//保证每段至少都有三位-------------
System.out.println(ip);
regex="0*(\\d{3})";
ip=ip.replaceAll(regex,"$1");//每段只保留三位
System.out.println(ip);
regex=" ";
String[] arr=ip.split(regex);//按照空格切
//定义一个TreeSet集合,利用元素自然排序
TreeSet<String > ts=new TreeSet<String>();
for (String str : arr )
{
ts.add(str);//添加
}
regex="0*(\\d+)";//把每段前面多余的0替换掉
for (String s : ts)
{
System.out.println(s.replaceAll(regex,"$1"));//把每段前面多余的0替换掉
}
}
}
(2)工作中对邮件地址进行校验
分析:校验一般是用正则表达式的匹配功能去做,进一步想到匹配的matches方法
例子:
/*
对邮箱地址进行校验
*/
package cn.dhj;
public class TestYouJian {
public static void main(String[] args){
String mail = "[email protected]";
String reg = "[0-9a-zA-Z_]+@[0-9a-zA-Z]+(\\.[a-zA-Z]+)+";
System.out.println(mail.matches(reg));
}
}