您的位置:首页 > 编程语言 > Java开发

Java笔记---正则表达式

2015-10-07 23:35 573 查看
一、正则表达式概述:
     符合一定规则的表达式。作用是专门用于操作字符串。虽然我们在前面学习了对于字符串的操作,但是我们在要去操作复杂的字符串时,如果还选用以前的方式,那么代码会变得很复杂,那么操作方便又快的方式就是正则表达式了。简化对字符串的复杂操作。
特点:用于一些特定的符号来表示一些代码操作。这样就简化了书写。所以学习正则表达式就是在学习一些特殊符号的使用。
public class RegexDemo {
public static void main(String[] args) {
chekQQ_1();
}

public static void chekQQ_1(){
String qq = "2450897";
//第一位是1-9的数字,第二位是0-9的数字并且出现了4-14次
String reg = "[1-9][0-9]{4,14}";

if(qq.matches(reg))//将规则和字符串相关联
System.out.println(qq+".....is ok");
else
System.out.println(qq+"......is  nono");
}

/*
* 对qq好进行校验 需求:5-15位,0不能开头,只能是数字
*
* 这种方式,是使用了String类中方法进行组合完成了需求,但是代码啊过于复杂
*/
public static void chekQQ() {
String qq = "2456897";
int len = qq.length();

if (len >= 5 && len <= 15) {
if (!(qq.startsWith("0"))) {//判断是否以0开头

try {
long l = Long.parseLong(qq);
System.out.println(l);
} catch (NumberFormatException e) {
System.out.println("出现非法字符");
}

/*char[] arr = qq.toCharArray();
boolean flag = true;
for (char ch : arr) {
if (!(ch >= '0' && ch <= '9')) {
flag = false;
break;
}
}
if (flag) {
System.out.println(qq);
}else{
System.out.println("非法字符");
}
*/
} else {
System.out.println("不可以以0开头");
}
}else{
System.out.println("必须是5到15位的数字");
}

}
}


在上面的代码中我们先使用了String的一系列的方法来对字符串进行校验,我们可以看出来,方法很多,而且很多判断。很复杂,然后我们直接使用异常来进行处理,代码还是显得很复杂,所以我们就用了第二种方法,正则表达式,我们可以看到上面的checkQQ_2这个方法我们使用了正则表达式来判断这个qq是否合法,我们在判断这个qq的时候只需要知道这个是不是正确的就行了,我们正则表达式就直接返回了true和false。代码变得非常的简单,本来好几行的代码,现在三句话就全部搞定,这样我们也看出了正则表达式的好处。
二、具体操作功能:
 1)、匹配:  String  matches方法。
字符类:
[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](减去)
预定义字符类:

.任何字符(与行结束符可能匹配也可能不匹配)
\d数字:[0-9]
\D非数字: [^0-9]
\s空白字符:[ \t\n\x0B\f\r]
\S非空白字符:[^\s]
\w单词字符:[a-zA-Z_0-9]
\W非单词字符:[^\w]
注意:在正则表达式中\是成对出现的,并不是转义字符。
Greedy数量词:

X?X,一次或一次也没有
X*X,零次或多次
X+X,一次或多次
X{n}X,恰好 n 次
X{n,}X,至少 n 次
X{n,m}X,至少 n 次,但是不超过 m 次
匹配是拿整个字符串根据规则去判断,如果判断到某部分为false了,就匹配失败,返回false
手机号匹配:
//手机号匹配
//并且是以13xxx 15xxx 18xxx
public static void checkTel(){
String tel = "";
String reg = "1[358]\\d{9}";
System.out.println(tel.matches(reg));
2)、切割:String  split();

为了可以让规则的结果被重复使用,可以将规则封装成一个组用()完成,组的出现都有编号,从1开始,想要使用已有的组,可以通过 \n(n就是组的编号)的形式来获取。
捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:

1((A)(B(C)))
2\A
3(B(C))
4(C)

public static void splitDemo(){
String str = "zhangsan lisi    wangwu";
//		str = "c:\\abc\\a.txt";
str = "adcaafghkkkkkasd";
//		String reg = " +";//按照多个空格来切割
//		String reg = "\\\\";
String reg = "(.)\\1+";//按照叠词来切割
String[] arr = str.split(reg);//按照规则进行切割
for(String s : arr){
System.out.println(s);
}
}
因为这些组的出现,我们也可以看出正则表达式的缺点:就是阅读性极差。

3)、替换 String replaceAll(); 

String str = "aasd12315612agah547789jfdh";//将字符串中的数字替换成#
replaceAll(str,"\\d{5,}","#");

String str1 = "aasdasdsdd2agahdhdghggjfdh";//将字符串中的叠词替换成#  //将重叠的字符替换成单个字母
//		replaceAll(str1,"(.)\\1+","&");
replaceAll(str1,"(.)\\1+","$1");
public
4000
static void replaceAll(String oldStr,String reg,String newStr){
oldStr  = oldStr.replaceAll(reg, newStr);//按照指定的规则进行替换
System.out.println(oldStr);
}
4)、获取:将字符串中符合规则的子串取出

 操作步骤:

  1、将正则表达式封装成对象

  2、让正则对象和要操作的字符串相关联

  3、关联后,获取正则匹配引擎

  4、通过引擎对符合规则的子串进行操作,比如:取出

/*4、获取:将字符串中符合规则的子串取出
*
* 操作步骤:
* 1、将正则表达式封装成对象
* 2、让正则对象和要操作的字符串相关联
* 3、关联后,获取正则匹配引擎
* 4、通过引擎对符合规则的子串进行操作,比如:取出

*/
import java.util.regex.*;
public class RegexDemo2 {
public static void main(String[] args) {
getDemo();
}
public static void getDemo(){
String str = "ming tian jiu yao fang jia le,da jia";
//	   str="123456";
//	   String reg = "[1-9]\\d{4,14}";
String reg = "\\b[a-z]{4}\\b";

//将规则封装成对象
Pattern p = Pattern.compile(reg);

//将正则对象和字符串相关联,获取匹配器对象
Matcher m = p.matcher(str);

//	   System.out.println(m.matches());//其实String类中的matches方法,用的就是Pattern和Matcher对象来完成的,只不过被String的方法封装后用起来较为简单,但是功能却单一

//将 规则作用到字符串上,并进行符合规则的子串查找
//	   boolean b = m.find();
//	   System.out.println(b);
//
//	   //获取匹配后的结果
//	   System.out.println(m.group());

while(m.find()){
System.out.println(m.group());
}
}
}


打印结果:


 我们在while循环中通过调用matches方法,我们可以看到返回的值是false,为什么会出现这种情况呢,因为我们的规则是作用于整个字符串,当前面四个与规则匹配完之后后面的空格已经不符合我们的规则,所以他返回了false,但是我们的指针还在继续走,这时候我们的指针就移到了t上,然后从t开始又继续匹配,后面的依次类推,所以第二次去匹配的时候是不会从头开始的,因为我们的索引发生了变化,同一个匹配器的索引是相同的。

正则表达式练习:

import java.util.TreeSet;

/*
*
*
* 到底使用四种功能中的哪一种呢?或者哪几个呢?
* 思路方式:
* 1、如果只想知道该字符串是否对错,用匹配
* 2、想要将已有的字符串变成另一个字符串,替换
* 3、想要按照自定义的方式将字符串变成多个字符串。切割,获取规则意外的字符串
* 4、想要拿到符合规则的字符串,获取。获取符合规则的字符串
*/
public class RegexTest {
public static void main(String[] args) {
// test_1();
// ipSort();
checkMail();
}

/*
* 需求:对邮件地址进行校验,
*/
public static void checkMail() {
String mail = "abc@sina.com";
String reg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}";// 较为精确的匹配

reg = "\\w+@+\\w+(\\.\\w+)+";// 相对不精确的匹配 但是1@1.1这样的地址他也匹配
System.out.println(mail.matches(reg));
}

/*
* 需求: 将下列字符串转成:我要学编程。
*/
public static void test_1() {
String str = "我我...我我...我要..要要...要要...学学学...学学...编编编...编程..程.程程...程...程";

/*
* 将已有的字符串变成另一个字符串,使用替换功能 1、先将.去掉 2、再将多个重复的内容变成单个内容
*/
str = str.replaceAll("\\.+", "");

str = str.replaceAll("(.)\\1+", "$1");
System.out.println(str);
}

/*
* 需求:192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30;
* 将ip地址进行地址段顺序的排序
*
*
* 还按照字符串自然顺序,只要让他们每一段都是三位即可 1、按照每一段需要最多的0进行补齐,那么每一段至少都能保证有3位
* 2、将每一段只保留三位,这样所有的ip地址都是每一段三位
*/
public static void ipSort() {
String ip = "192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";
ip = ip.replaceAll("(\\d+)", "00$1");
ip = ip.replaceAll("0*(\\d{3})", "$1");
String[] str = ip.split(" +");

// 定义一个TreeSet集合,他会自动按照自然顺序排序
TreeSet<String> ts = new TreeSet<String>();

for (String s : str) {
ts.add(s);
}

for (String s : ts) {
System.out.println(s.replaceAll("0*(\\d+)", "$1"));
}
}

}
正则表达式之网页爬虫:
所谓的网页爬虫就是一段小程序,这段程序会去将网页上指定的信息取出来。我们以获取网页中的邮件地址为例:

import java.io.*;
import java.net.*;
import java.util.regex.*;

public class RegexTest2 {
public static void main(String[] args) throws Exception {
getMails_2();
}

/*
* 从网上获取邮件地址
*/

public static void getMails_2() throws Exception {
URL url = new URL("http://192.168.70.1:8888//myweb/mail.html");

URLConnection conn = url.openConnection();
BufferedReader bufr = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
String line = null;
String reg = "\\w+@+\\w+(\\.\\w+)";
Pattern p = Pattern.compile(reg);
while ((line = bufr.readLine()) != null) {
match(line, p);
}
}

/*
* 获取指定文档中的邮件地址 使用获取功能,Pattern Matcher
*/
public static void getMails() throws Exception {
BufferedReader bufr = new BufferedReader(new FileReader("c:\\mail.txt"));

String line = null;
String reg = "\\w+@+\\w+(\\.\\w+)";//定义邮箱规则
Pattern p = Pattern.compile(reg);//将规则封装成对象
while ((line = bufr.readLine()) != null) {
match(line, p);
}
}

public static void match(String str, Pattern p) {

Matcher m = p.matcher(str);
while (m.find()) {//先进行查找
System.out.println(m.group());//打印
}
}

}

以上就是正则表达式的内容,文章还有很多的不足之处,望指出!谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: