您的位置:首页 > 职场人生

黑马程序员-正则表达式

2012-05-18 01:01 417 查看
---------------------- android培训java培训、期待与您交流! ----------------------

正则表达式:符合一定规则的操作字符串的表达式

特点:将操作字符串的代码封装成特定字符 由特定字符组成正则表达式。这样可以简化代码的书写。。。。

所以学习正则表达式,就是在学习一些特殊符号的使用。

好处:可以简化对字符串的复杂操作。

弊端:符号定义越多,正则越长,阅读性越差。

正则字符

构造 匹配

字符
x字符 x
\\反斜线字符
\0n带有八进制值 0 的字符 n (0 <= n <= 7)
\0nn带有八进制值 0 的字符 nn (0 <= n <= 7)
\0mnn带有八进制值 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 的控制符
字符类
[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]
边界匹配器
^行的开头
$行的结尾
\b单词边界
\B非单词边界
\A输入的开头
\G上一个匹配的结尾
\Z输入的结尾,仅用于最后的结束符(如果有的话)
\z输入的结尾

正则表达式中具有特定意义的字符注意一定的转义 如果没有在字符串的转义里定义就得经过2次转义。。

正则表达式中.代表所有字符的意思 所有你不想让它代表所有字符的意思的话可以写到一对中括号内如[.] 也可以用转义字符转义 如果要转义的话要用2个转义字符如\\.

\.这样写编译不会通过因为正则表达式是写在字符串内的 字符串检测到子窜里有转义符所有就会先被字符串转义而字符串转义里面没有\. 所有编译器不识别报错。。

\\.先被字符串转义成\. 在经过正则表达式转义 所有在字符串转义里面没有的要经过2次转义 而字符串转义里面已定义的只要被字符串转义就可以了 正则表达式里面可以转义也可以不转义 如\\n和\n 都是可以的

组是正则表达式用来封装部分正则的封装体 就跟函数体里封装的是代码一样 组可以内嵌 就跟类里面还可以封装类部类一样 每个组都有指针 通过指针操作组 指针0表示整个正则表达式 所以组的指针从1开始 在正则表达式内部调用组用\指针 由于要经过字窜转义所以写成\\指针 在参数列表内调用定一个正则表达式的组应该用$指针

捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:

1 ((A)(B(C)))
2 \A
3 (B(C))
4 (C)
组零始终代表整个表达式。

正则表达式操作步骤: 当然头前3个功能也可以不完全按照这个来直接操作String或Pattern类也可以 如果是地4个功能或其他功能就要按照这个来了

1.按指定的模式将正则表达式编译封装成正则表达式对象

通过Pattern类的compile方法

static Pattern
compile(String regex)


将给定的正则表达式编译到模式中。
static Pattern
compile(String regex,int flags)


将给定的正则表达式编译到具有给定标志的模式中。
2. 让正则表达式对象和要操作的字符串序列按模式执行匹配操作创建获取匹配引擎 也可以理解为让正则对象和要操作的字符串相关联,关联后,获取正则匹配引擎。

通过Pattern类的matcher方法

Matcher
matcher(CharSequence input)


创建匹配给定输入与此模式的匹配器。
3.通过匹配器引擎对符合规则的子串进行操作,比如取出。

具体操作功能:

1,匹配:用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。

String类

boolean
matches(String regex)


告知此字符串是否匹配给定的正则表达式
Pattern类

staticboolean
matches(String regex,CharSequence input)


编译给定正则表达式并尝试将给定输入与其匹配。
Matcher类

boolean
matches()


尝试将整个区域与模式匹配。
String类和Pattern类的matches方法调用的是Matcher类的matches方法 被String 和Pattern的方法封装后,用起来较为简单。但是功能不够多。就如Math类的random方法调用的Random类的nextDoube 它只能直接生产0到1的双精度小数 Random的方法丰富的多可以直接生成整数boolean等其他类型的数

2,切割:用规则匹配整个字符串,获取不符合规则的子窜

String类

String[]
split(String regex)


根据给定正则表达式的匹配拆分此字符串。
String[]
split(String regex,int limit)


根据匹配给定的正则表达式来拆分此字符串。
Pattern类

String[]
split(CharSequence input)


围绕此模式的匹配拆分给定输入序列。
String[]
split(CharSequence input,int limit)


围绕此模式的匹配拆分给定输入序列。
3,替换:用规则匹配整个字符串 按条件用新的子窜替换符合规则的子窜 replacement为新的子窜

String
replaceAll(String regex,String replacement)


使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。

String
replaceFirst(String regex,String replacement)


使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
String


replaceAll(String replacement)


替换模式与给定替换字符串相匹配的输入序列的每个子序列。

String


replaceFirst(String replacement)


替换模式与给定替换字符串匹配的输入序列的第一个子序列。

4,获取:将字符串中的符合规则的子串取出。

Matcher类

当没执行find方法是不能执行group start end方法的还有其他方法也不能执行具体什么方法可以查api或者Eclipse上试 如果你没执行find 方法执行了这几种方法会抛IllegalStateException异常 该异常extendsRuntimeException 在非法或不适当的时间调用方法时产生的信号。换句话说,即
Java 环境或 Java 应用程序没有处于请求操作所要求的适当状态下。

这个机制跟迭代器的hasNext()方法很像 不同之处在于你不执行迭代器的hasNext方法 也可以执行next方法 前提迭代器里有数据不然也会是运行期错误。而matcher的那几个方法需要用到执行find后的指针 所以没find是会报错的 而且你操作了指针方法掉完以后 指针还会在你调用的地方不会自动返回到调用之前这跟迭代器一样。 Matcher对象需要通过reset方法重置指针或从指定的指针开始 这点上迭代器没有设置或重置指针的方法如果非要说有的话就得重新搞个迭代器 而且当有多个迭代器操作同个容器只能用一个迭代器操作容器的元素
用多个操作会导致快速失败异常 当然带参数的ListIterator除外。。。。

reset 和头前3个功能的方法没执行find 是是可以执行的

boolean
find()


尝试查找与该模式匹配的输入序列的下一个子序列。
boolean
find(int start)


重置此匹配器,然后尝试查找匹配该模式、从指定索引开始的输入序列的下一个子序列。
String
group()


返回由以前匹配操作所匹配的输入子序列。
String
group(int group)


返回在以前匹配操作期间由给定组捕获的输入子序列。
int
start()


返回以前匹配的初始索引。
int
start(int group)


返回在以前的匹配操作期间,由给定组所捕获的子序列的初始索引。
int
end()


返回最后匹配字符之后的偏移量。
int
end(int group)


返回在以前的匹配操作期间,由给定组所捕获子序列的最后字符之后的偏移量。
Matcher


reset()


重置匹配器。

Matcher


reset(CharSequence input)


重置此具有新输入序列的匹配器。

以上四种功能到底用四种功能中的哪一个呢?或者哪几个呢?

思路方式:

1,如果只想知道该字符是否对是错,使用匹配。

2,想要将已有的字符串变成另一个字符串,替换。

3,想要按照自定的方式将字符串变成多个字符串。切割。获取规则以外的子串。

4,想要拿到符合需求的字符串子串,获取。获取符合规则的子串。

import static java.lang.System.out;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Comparator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexDemo {

public static void main(String[] args) {
String regex;
String qq="233322232";
regex="[1-9]\\d{4,13}";
checkQQ(qq,regex);

String tel="13986868886";
regex="1[358]\\d{9}";
checkTel(tel,regex);

String mail="adadsfadsf@163.COM";
regex="\\w{6,14}@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";//相对精准
regex="\\w{6,14}@\\w+(\\.\\w+)+";//不太精准
checkMail(mail,regex);

//按照.切割 由于.在正则表达式中代表所有字符所有要转义 而又没在字符串转义里注册所以要用到2个转义符号
String name="zhangsan.lisi.wangwu";
regex="\\."; //或者写成regex=[.];
split(name,regex);

//按照叠词切割
name="erkktyqqquizzzzzo";
regex="(.)\\1+";
split(name,regex);

//按照任意个空格进行切割
name="zhangsan wangwu zhaoliu lisi wangqi ";
regex=" +";
split(name,regex);

//将5位以上的数字替换成$号
String str ="wer1389980000ty1234564uiod234345675f";
regex="\\d{5,}";
String newStr="\\$"; //$要被转义因为在正则表达式中它用来调用组。。
replaceAll(str,regex,newStr);

//将重复出现的叠词替换成单个字母
str= "erkktyqqquizzzzzo";
regex="(.)\\1+";
newStr="$1"; //$通过组指针调用组
replaceAll(str,regex,newStr);

//去掉空格和.在把叠字换成单个的字
textFormat();

//获取符合规则的字串和指针
getDemo();

//ip地址排序
ipOldSort();
ipSort();
//从文件和网上获取Email地址
getEmailForFile();
getEmailForURL();
}
///////////////////////////////匹配/////////////////////////////////
/**
* 匹配
* QQ号码是否合法
* 5到14位 开头不能为0 都是数字
*/
static void checkQQ(String qq,String regex){
out.println(qq.matches(regex));
}

/**
匹配
手机号段只有 13xxx 15xxx 18xxxx
*/
static void checkTel(String tel,String regex){
out.println(tel.matches(regex));
}

/**
* 匹配
* Email地址是否合法
*/
static void checkMail(String mail,String regex){
out.println(mail.matches(regex));
}
///////////////////////////////End////////////////////////////////////////

///////////////////////////////切割/////////////////////////////////
/**
* 将不符号正则表达式部分的取出来
*/
static void split(String str,String regex){
String strs[]=str.split(regex);
out.println(Arrays.toString(strs));
}

/**
*用规则匹配整个字符串 按条件用新的子窜替换符合规则的子窜
*/
static void replaceAll(String str,String regex,String newStr){
out.println(str.replaceAll(regex, newStr));
}

////////////////////////////////END/////////////////////

/////////////////////////////获取////////////////////////////////
public static void getDemo(){
String str = "ming tian jiu yao fang jia le ,da jia。";
System.out.println(str);
String regex = "\\b[a-z]{4}\\b";

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

//将正则对象和字符串按模式执行匹配操作获取匹配引擎
Matcher m = p.matcher(str);

//find将规则作用到字符串上,并进行符合规则的子串查找。

//如果这里执行了m.matches(regex);那么指针将从t开始
while(m.find()){
//group用于获取匹配后结果。
System.out.println(m.group());
//start end 用来获取匹配前后指针
System.out.println(m.start()+"...."+m.end());
}
}

////////////////////////////////END//////////////////////////////////////
/**
*需求:
*将下列字符串转成:我要学编程.
*/
static void textFormat(){
String str = "我我...我 我我...我 要要..要 要...要要...学" +
"学学....学学...编.......编 编...编程..程.程程...程...程";
//可以先把.和空格去掉在把重复的字编程单个的字
String regex="[. ]+";
replaceAll(str,regex, "");
str=str.replaceAll(regex, "");
regex="(.)\\1+";
replaceAll(str,regex,"$1");
}

/**
* 将ip地址进行地址段顺序的排序。
* 这是没用正则表达式的情况
*/
static void ipOldSort(){

String ip="192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30";
String[] ips=ip.split(" ");
Arrays.sort(ips,new Comparator<String>(){
@Override
publicint compare(String s1,String s2){
//.在正则表达式里表示所有字符不想表示所有字符的话就一定记得转义
//比较2个数字字符串的大小不要用compareTo比较 要转换成Integer在比较
String[] tmpS1s=s1.split("[.]");
String[] tmpS2s=s2.split("\\.");
int ret=0;
for(int i=0;i<tmpS1s.length;i++){
ret=Integer.parseInt(tmpS1s[i])-Integer.parseInt(tmpS2s[i]);
if(ret!=0){
break;
}
}
return ret;
}
});
out.println("old ip sort:"+Arrays.toString(ips));
}

static void ipSort(){
String ip="192.168.1.2 11.1.3.4 0.32.32.34 10.2.4.3 2.3.4.2";
//首先把每个IP地址的每个段头前都补2个0 在让每个段都成3位
String regex="(\\d+)";
ip=ip.replaceAll(regex, "00$1");
regex="0*(\\d{3})";
ip=ip.replaceAll(regex, "$1");
//在通过空格切割这个字串
String[] ips=ip.split(" +");
//通过Arrays.sort进行排序
Arrays.sort(ips);
//输出
for(int index=0;index<ips.length;index++){
ips[index]=ips[index].replaceAll("0*(\\d+)","$1");
}
System.out.println("new ip sort:"+Arrays.toString(ips));
}

/**
* 更具文件爬Email
*/
static void getEmailForFile(){
try {
FileInputStream fis=new FileInputStream("g:/mail.txt");
getEmail(fis);
} catch (FileNotFoundException e) {
System.out.println("g:/mail.txt文件不存在或者是目录或权限不够或隐藏等等");
}

}

static void getEmailForURL(){
try {
InputStream in=new URL("http://192.168.1.245:8080/").openStream();
} catch (MalformedURLException e) {
System.out.println("建立连接失败请检查域名端口是否错误");
} catch (IOException e) {
System.out.println("IO错误");
}

}
/**
* 网页爬虫(蜘蛛)
*/
static void getEmail(InputStream in){
StringBuilder sb=new StringBuilder();
byte[] buf=new byte[1024];
try {
for(int len;(len=in.read(buf))!=-1;){
sb.append(new String(buf,0,len));
}
} catch (IOException e) {
System.out.println("IO流读取操作错误");
}finally{
if(in!=null){
try {
in.close();
} catch (IOException e) {
System.out.println("IO输入流关闭错误");
}
}
}
String regex="(\\w)+@\\w+(\\.\\w{2,})+";
Pattern pattern=Pattern.compile(regex);
Matcher matcher=pattern.matcher(sb.toString());
while(matcher.find()){
System.out.println(matcher.group());
}
}

}



---------------------- android培训java培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net/heima
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: