------- android培训、java培训、期待与您交流! ----------
一.概述
1.概念:符合一种规则的表达式。
2.作用:用于操作字符串。
3.特点:用一些特定的符号来表示一些代码操作,简化书写。
4.好处:可以简化对字符串的复杂操作。
5.弊端:符号定义越多,正则越长,阅读性越差。
二.常见符号的定义
1.字符
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 的控制符
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&&[^n-p]] a到z,而非n到p:[a-lq-z](减去)
3. 预定义字符类
\d 数字[0-9] 注意:在java中\\成对出现 \\d
\D 非数字[^0-9]
\s 空白字符: [ \t\n\x0B\f\r]
\S 非空白字符: [^\s]
\w 单词字符 : [a-zA-Z_0-9]
\W 非单词字符: [^\w]
4. Greedy数量词
X? X,一次或一次也没有
X* X, 零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m
5.边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾
6.组和捕获
捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C)))中,存在四个这样的组:
((A)(B(C)))
\A
(B(C))
(C)
组零始终代表整个表达式。
以 (?) 开头的组是纯的非捕获组,它不捕获文本,也不针对组合计进行计数。
三.正则表达式的具体操作功能
1.匹配:
String类中的matches()方法,用规则匹配整个字符串,只要有一处不符合规则,返回false。
代码:
public class MatchesDemo {
public static void main(String[] args) {
// 校验qq
checkQQ_1();// 普通方式
checkQQ_2();// 使用正则表达式
// 校验手机号码
checkPhoneNumber("18215160718");
// 校验邮箱
checkMail("12345@qq.com");
}
/*
* 对QQ号码进行校验 要求:5~15 0不能开头,只能是数字
*/
// 普通校验方式,使用了String类中的方法,进行组合完成了需求。但是代码过于复杂。
public static void checkQQ_1() {
String qq = "1882345a0";
int len = qq.length();
if (len >= 5 && len <= 15) {
if (!qq.startsWith("0"))// Integer.parseInt("12a");NumberFormatException
{
try {
long l = Long.parseLong(qq);
System.out.println("qq:" + l);
} catch (NumberFormatException e) {
System.out.println("出现非法字符.......");
}
} else {
System.out.println("不可以0开头");
}
} else {
System.out.println("长度错误");
}
}
// 使用正则表达式
public static void checkQQ_2() {
String qq = "12345";
// 定义规则
String regex = "[1-9][0-9]{4,14}";
// 调用matches()方法
boolean flag = qq.matches(regex);
if (flag) {
System.out.println("qq" + "是合法的!");
} else {
System.out.println("qq不合法");
}
}
/*
* 校验手机号码
*/
public static void checkPhoneNumber(String phoneNumber) {
// 定义规则,校验手机号码
String regex = "1[3458]\\d{9}";
boolean flag = phoneNumber.matches(regex);
if (flag) {
System.out.println("手机号正确");
} else {
System.out.println("手机号码非法");
}
}
/*
* 校验邮箱地址
*/
public static void checkMail(String mail) {
// 定义规则,校验邮箱
String mailRegex = "\\w+@\\w+\\.[a-zA-Z]{2,4}";
boolean flag = mail.matches(mailRegex);
if (flag) {
System.out.println("邮箱格式正确");
} else {
System.out.println("邮箱格式错误");
}
}
}
2.切割:
String类中的split()方法。
代码:
/*
* 正则表达式的第二个功能:
* 切割
* String split()
* */
public class SplitDemo {
public static void main(String[] args) {
split("zhangsan.lisi.wangwu","\\.");
split("c:\\abc\\a.txt","\\\\");
/* 按照叠词完成切割*/
split("erkktyqqquizzzzzo","(.)\\1+");
}
// 按照正则表达式切割
public static void split(String str, String reg) {
// String reg1 = " +";//按照多个空格来进行切割
// String reg2="\\.";//按 .切割
// String reg3="(.)\\1+";//按照叠词切割
String[] arr = str.split(reg);
System.out.println(arr.length);
for (String s : arr) {
System.out.println(s);
}
}
}
按照叠词完成切割:
为了可以让规则的结果被重用,可以将规则封装成一个组。用()完成。组的出现都有编号。
编号从1开始。 想要使用已有的组可以通过 \n(n就是组的编号)的形式来获取。
3.替换
String类中的replaceAll( String regex, String str);
如果regex中定义了组,可以在第二个参数中通过$符号获取正则表达式中已有的组。
代码:
/*
* 正则表达式的第三个功能:
* 替换
* String replaceAll();
*
* */
public class ReplaceDemo {
public static void main(String[] args) {
String str = "wer1389980000ty1234564uiod234345675f";
//将字符串中的数字替换成#。
replace(str,"\\d{5,}","#");
String str2 = "erkktyqqquizzzzzo";
//将重叠的字符替换成单个字母。zzzz->z $1表示获取组1
replace(str2, "(.)\\1+", "$1");
}
public static void replace(String str, String reg, String newStr) {
str = str.replaceAll(reg, newStr);
System.out.println(str);
}
}
4.获取
将字符串中符合规则的子串取出。
步骤:
将正则表达式封装成对象。
让正则对象和要操作的字符串相关联。
关联后,获取正则匹配引擎。
通过引擎对符合规则的字符串进行操作。
代码:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/*正则表达式的第四个功能。
*获取:将字符串中的符合规则的子串取出。
**/
class RegexDemo2 {
public static void main(String[] args) {
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);
// System.out.println(m.matches());//其实String类中的matches方法。用的就是Pattern和Matcher对象来完成的。
// 只不过被String的方法封装后,用起来较为简单。但是功能却单一。
// boolean b = m.find();//将规则作用到字符串上,并进行符合规则的子串查找。
// System.out.println(b);
// System.out.println(m.group());//用于获取匹配后结果。
// System.out.println("matches:"+m.matches()); //false;
while (m.find()) {
System.out.println(m.group());
System.out.println(m.start() + "...." + m.end()); // 包含头,不包含尾
}
}
}
功能的选择:
如果只想知道该字符串是对是错------匹配。
如果将已有的字符串变成另一个字符串------替换。
想要按照自定义的方式将字符串变成多个字符串------切割(获取规则以外的字符串)。
想要拿到符合要求的字符串子串-----获取。
四.练习
代码:
import java.util.TreeSet;
class RegexText {
public static void main(String[] args) {
test();
sort();
}
/*
* 需求: 将下列字符串转成:我要学编程.
*
* 将已有字符串变成另一个字符串。使用 替换功能。
* 1 可以先将 . 去掉。
* 2 在将多个重复的内容变成单个内容。
*/
public static void test() {
String str = "我我...我我...我要..要要...要要...学学学....学学...编编编...编程..程.程程...程...程";
//去掉.
str = str.replaceAll("\\.", "");
System.out.println(str);
//去掉重复的内容
str = str.replaceAll("(.)\\1+", "$1");
System.out.println(str);
}
/*
* 需求:对邮件地址进行校验。
*/
public static void checkMail() {
String mail = "abc12@sina.com";
mail = "1@1.1";
String reg = "[a-zA-Z0-9_]+@[a-zA-Z0-9]+(\\.[a-zA-Z]+)+";// 较为精确的匹配。
reg = "\\w+@\\w+(\\.\\w+)+";// 相对不太精确的匹配。
// mail.indexOf("@")!=-1
System.out.println(mail.matches(reg));
}
/*
* 192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30
* 将ip地址进行地址段顺序的排序。
*
*
* 还按照字符串自然顺序,只要让它们每一段都是3位即可。
* 1,按照每一段需要的最多的0进行补齐,那么每一段就会至少保证有3位。
* 2,将每一段只保留3位。这样,所有的ip地址都是每一段3位。
*/
public static void sort() {
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");
System.out.println(ip);
ip = ip.replaceAll("0*(\\d{3})", "$1");
System.out.println(ip);
String[] arr = ip.split(" ");
TreeSet<String> ts = new TreeSet<String>();// 排序用Arrays.sort() 也可以
for (String s : arr) {
ts.add(s);
}
for (String s : ts) {
System.out.println(s.replaceAll("0*(\\d+)", "$1"));//把每段前面多余的0替换掉
}
}
}
五.网页爬虫(蜘蛛)
是一个功能,用于搜集网络上的指定信息
代码:
import java.io.*;
import java.util.regex.*;
import java.net.*;
/*
网页爬虫(蜘蛛)
*/
class RegexText2 {
public static void main(String[] args) throws Exception
{
getMails();
getMails_1();
}
//获取网页中的邮箱地址
public static void getMails_1() throws Exception
{ //URL
URL url=new URL("http://127.0.0.1:8080/myweb/mail.html");
//获取连接器
URLConnection conn=url.openConnection();
//创建流
BufferedReader bufIn=new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line=null;
//定义正则表达式
String mail="\\w+@\\w+(\\.+\\w+)+";
//将正则表达式封装成对象
Pattern p=Pattern.compile(mail);
while((line=bufIn.readLine())!=null)
{
//获取匹配器引擎
Matcher m=p.matcher(line);
while(m.find())//查找
{
System.out.println(m.group());//打印匹配后的结果
}
}
}
// 获取文本中的邮箱地址
// 使用获取功能 Pattern Matcher
public static void getMails() throws Exception
{ //创建流,并关联文件
BufferedReader bufr=new BufferedReader(new FileReader("E:\\Eclipse_workspace\\javaday25\\src\\day25\\mail.txt"));
String line=null;
//定义正则表达式
String mail="\\w+@\\w+(\\.+\\w+)+";
//将正则表达式封装成对象
Pattern p=Pattern.compile(mail);
while((line=bufr.readLine())!=null)
{
//获取匹配器引擎
Matcher m=p.matcher(line);
while(m.find())//查找
{
System.out.println(m.group());//打印匹配后的结果
}
}
}
}