学习地址:【韩顺平讲Java】Java 正则表达式专题Java 正则表达式 | 菜鸟教程 (runoob.com)感谢韩老师的讲解视频,十分感谢!!!
1. 认识正则表达式
首先通过示例体验正则表达式的强大功能。
随便找段话,找出所有4个连续数字的式子包com.zhuang.regex;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
/**
* @类名Regex01
* @Description 体验正则表达式的威力
* @日期2021/5/23 12:58
* @由戴尔创建
*/
公共类Regex01 {
公共静态无效主(字符串[] args){
String content="1998年12月8日,第二代Java平台J2EE企业版发布。 1999年6月,Sun发布了"+
"第二代Java平台(简称Java2)的3个版本:J2ME(Java2 Micro Edition,微型版本的Java2平台" +
"版),用于移动、无线和有限资源环境; J2SE(Java 2 标准版,Java 2 平台" +
"标准版),适用于桌面环境; J2EE(Java 2Enterprise Edition,Java 2平台的企业版),应该"+
"用于与基于Java 的应用程序服务器一起使用3443。 Java 2平台的发布是Java"+发展中最重要的一步
“标志着Java应用程序普及开始的里程碑9889”;
//目标匹配所有四个数字
//\d 代表任意数字
String regStr="\d\d\d\d";
//创建模式对象,即正则表达式对象
模式模式=Pattern.compile(regStr);
//创建匹配器,按照正则表达式的规则匹配内容字符串
匹配器matcher=pattern.matcher(content);
匹配器.find();
while (matcher.find()){
System.out.println("找到-"+matcher.group(0));
}
}
}结果
通过几个公式,就可以准确找到连续的四个数字!
接下来分析两个重要的表达式
matcher.find();功能:考虑分组
什么是分组?例如,(\d)(\d) 表达式中带有() 表示分组,第一个() 表示组1,第二个() 表示组2。
根据指定的规则,找到满足(20)(66)等规则的子串。找到后,设置子字符串的开始索引记录到matcher对象的属性int[]组; 2.1 groups[0]=0,并将子字符串的结束索引加1。该值记录在groups[1]=42.2 记录1 group()匹配到的字符串groups[2]=0 groups[3]=22.3 记录2 group()匹配的字符串groups[4]=2 groups[5]=42.4。如果还有更多组.同时记录oldLast的值,即子串的结束索引+1的值,即35。下次执行find时,从35开始匹配matcher.group();。先看源码
公共字符串组(int组){
如果(第一个0)
抛出新的IllegalStateException("未找到匹配项");
if (组0 || 组groupCount())
throw new IndexOutOfBoundsException("没有组" + group);
if ((组[组*2]==-1) || (组[组*2+1]==-1))
返回空值;
return getSubSequence(groups[group * 2], groups[group * 2 + 1]).toString();
}根据groups[0]=31和groups[1]=35的记录位置,截取从content开始的子串并返回
即[31,35)包含31但不包含索引为35的位置
如果再次指向find方法,仍然会按照上面的分析执行。
我们修改一下原来的代码,看看分组是如何匹配的。
更改字符串regStr="\d\d\d\d"; to String regStr="(\d\d)(\d\d)";
debug启动断点位置如下
包com.zhuang.regex;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
/**
* @类名Regex01
* @Description 体验正则表达式的威力
* @日期2021/5/23 12:58
* @由戴尔创建
*/
公共类Regex01 {
公共静态无效主(字符串[] args){
String content="1998年12月8日,第二代Java平台J2EE企业版发布。 1999年6月,Sun发布了"+
"第二代Java平台(简称Java2)的3个版本:J2ME(Java2 Micro Edition,微型版本的Java2平台" +
"版),用于移动、无线和有限资源环境; J2SE(Java 2 标准版,Java 2 平台" +
"标准版),适用于桌面环境; J2EE(Java 2Enterprise Edition,Java 2平台的企业版),应该"+
"用于与基于Java 的应用程序服务器一起使用3443。 Java 2平台的发布是Java"+发展中最重要的一步
“标志着Java应用程序普及开始的里程碑9889”;
//目标匹配所有四个数字
//\d 代表任意数字
String regStr="(\d\d)(\d\d)";
//创建模式对象,即正则表达式对象
模式模式=Pattern.compile(regStr);
//创建匹配器,按照正则表达式的规则匹配内容字符串
匹配器matcher=pattern.matcher(content);
匹配器.find();
while (matcher.find()){
System.out.println("找到-"+matcher.group(0));
System.out.println("找到的第一组值-"+matcher.group(1));
System.out.println("第二组找到的值-"+matcher.group(2));
}
}
}启动后进入方法查看属性看到groups中的索引元素在增加!小结如果正则表达式有(),则表示分组
提取匹配字符串的规则如下:
group(0)代表匹配的子串
group(1) 表示匹配子串中的第一组字符串
group(2) 表示匹配子串中的第二组字符串
但组数不能超过限制
2. 正则表达式介绍
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到z 之间的字母)和特殊字符(称为“元字符”)。
正则表达式使用单个字符串来描述和匹配一系列符合某种语法规则的字符串。
元字符按功能大致分为
限定符选择匹配字符组组合及后向引用字符特殊字符字符匹配字符定位符
2.1 元字符-转义号\
\符号说明:当我们使用正则表达式检索某些特殊字符时,需要使用转义符号,否则搜索无结果
注意:在Java的正则表达式中,两个\代表其他语言中的一个。
包com.zhuang.regex;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
/**
* @类名Regex02
* @Description 演示转义字符的使用
* @日期2021/5/23 13:37
* @由戴尔创建
*/
公共类Regex02 {
公共静态无效主(字符串[] args){
字符串内容="abc$(a.bc(123( )";
//匹配(=\(
//匹配。=\. //字符串regStr="\.";
//字符串regStr="\d\d\d";
String regStr="\d{3}";
模式模式=Pattern.compile(regStr);
匹配器matcher=pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到" + matcher.group(0));
}
}
}在
String regStr="\d\d\d";//可以这样写
String regStr="\d{3}";
2.2 元字符-字符匹配符
包com.zhuang.regex;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
/**
* @类名Regex03
* @Description 演示转义字符的使用
* @日期2021/5/23 13:58
* @由戴尔创建
*/
公共类Regex03 {
公共静态无效主(字符串[] args){
字符串内容="a11c8abc _ABCy @";
String regStr="[a-z]";//匹配a-z之间的任意字符
//String regStr="[A-Z]";//匹配A-Z之间的任意字符
//String regStr="abc";//匹配abc字符串【默认区分大小写】
//String regStr="(?i)abc";//匹配abc字符串【不区分大小写
//String regStr="[0-9]";//匹配0-9之间的任意字符
//String regStr="[^a-z]";//匹配不在a-z之间的任意字符
//String regStr="[^0-9]";//匹配任何不在0-9之间的字符
//String regStr="[abcd]";//匹配abcd中任意字符
//String regStr="\D";//匹配任何非0-9的字符
//String regStr="\w";//匹配大小写英文字母、数字、下划线
//String regStr="\W";//匹配相当于[^a-zA-Z0-9_]
//\s 匹配任何空白字符(空格、制表符等)
//字符串regStr="\s";
//\S 匹配任何非空白字符,与\s 相反
//字符串regStr="\S";
//。匹配除n 之外的所有字符。如果你想匹配。本身,您需要使用\.
//字符串regStr=".";
//阐明
//1.创建Pattern对象时,指定Pattern.CASE_INSENSITIVE,这意味着匹配不区分大小写。
模式pattern=Pattern.compile(regStr/*, Pattern.CASE_INSENSITIVE*/);
匹配器matcher=pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到" + matcher.group(0));
}
}
}
2.3 元字符-选择匹配字符
在匹配某个字符串时是选择性的。它可以匹配这个或那个。您需要使用匹配符号|
符号符号示例解释|匹配“|”之前或之后的表达式ab|cdab 或cdpackage com.zhuang.regex;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
/**
* @类名Regex04
* @Description选择匹配器
* @日期2021/5/23 14:04
* @由戴尔创建
*/
公共类Regex04 {
公共静态无效主(字符串[] args){
String content="康小庄康康康";
字符串regStr="kang|kang|携带";
模式pattern=Pattern.compile(regStr/*, Pattern.CASE_INSENSITIVE*/);
匹配器matcher=pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到" + matcher.group(0));
}
}
}
2.4 元字符-限定符
用于指定前面的字符和组合项连续出现多少次
包com.zhuang.regex;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
/**
* @类名Regex05
* @Description 用一句话描述该类的功能
* @日期2021/5/23 14:15
* @由戴尔创建
*/
公共类Regex05 {
公共静态无效主(字符串[] args){
字符串内容="a211111aaaaaahello";
//a{3},1{4},\d{2}
//String regStr="a{3}";//表示匹配aaa
//String regStr="1{4}";//表示匹配1111
//String regStr="\d{2}";//表示匹配任意两位数字字符
//a{3,4},1{4,5},\d{2,5}
//详情:java匹配默认为贪心匹配,即尽可能多的匹配
//字符串regStr="a{3,4}"; //表示匹配aaa或aaaa
//字符串regStr="1{4,5}"; //表示匹配1111或者11111
//字符串regStr="\d{2,5}"; //匹配2位数字或3,4,5
//1+
//字符串regStr="1+"; //匹配一个或多个1
//字符串regStr="\d+"; //匹配一个或多个数字
//字符串regStr="1*"; //匹配0个1或多个1
//演示?的使用,遵守贪心匹配
字符串regStr="a1?"; //匹配a或a1
模式pattern=Pattern.compile(regStr/*, Pattern.CASE_INSENSITIVE*/);
匹配器matcher=pattern.matcher(content);
while (matcher.find()) {
System.out.println("找到" + matcher.group(0));
}
}
}
2.5 元字符-定位符
定位符,指定要匹配的字符串出现的位置,例如字符串的开头或结尾
符号含义示例描述匹配输入^指定起始字符^[0-9]+[a-z]*以至少1个数字开头,后跟任意小写字母的字符串123,6aa$指定结束字符^[0-9] \\-[a-z]+$ 以1 个数字开头,后跟连接符“-”,并至少以1 个小写字母结尾的字符串1-a\b 匹配目标字符串的边界kang\b这里所说的字符串的边界是指子字符串之间的空格,或者是目标字符串的结束位置spkang, hhkang\B 匹配目标字符串的非边界kang\B 和\b 的含义正好相反kangzk ,niukangpackage com.zhuang.regex;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
/**
* @类名Regex06
* @Description 演示定位器的用法
* @日期2021/5/23 14:24
* @由戴尔创建
*/
公共类Regex06 {
公共静态无效主(字符串[] args){
String content="康小庄spkang nnkang";
//字符串内容="123-abc";
//以至少1个数字开头,后跟任意数量的小写字母的字符串
//字符串regStr="^[0-9]+[a-z]*";
//至少以1个数字开头,且必须以至少1个小写字母结尾
//字符串regStr="^[0-9]+\-[a-z]+$";
//汉代表匹配边界【这里的边界是指:匹配字符串的末尾,//也可以是带空格的子串后面]
String regStr="kang\b";
//\b的含义正好相反
//String regStr="kang\B";
模式模式=Pattern.compile(regStr);
匹配器matcher=pattern.matcher(content);
while (matcher.find()) {
System.out.println("find=" + matcher.group(0));
}
}
}
3. 分组
包com.zhuang.regex;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
/**
* @类名Regex07
* @Description 分组演示
* @日期2021/5/23 14:34
* @由戴尔创建
*/
公共类Regex07 {
公共静态无效主(字符串[] args){
String content="康晓庄s7789 nn1189h";
//1. matcher.group(0) 获取匹配的字符串
//2. matcher.group(1) 获取匹配字符串的第一组内容
//3. matcher.group(2) 获取匹配字符串的第二组内容
//字符串regStr="(\d\d)(\d\d)"; //匹配4位数字的字符串
//姓名
分组: 即可以给分组取名 String regStr = "(?\d\d)(?\d\d)";//匹配 4 个数字的字符串 Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); while (matcher.find()) { System.out.println("找到=" + matcher.group(0)); System.out.println("第 1 个分组内容=" + matcher.group(1)); System.out.println("第 1 个分组内容[通过组名]=" + matcher.group("g1")); System.out.println("第 2 个分组内容=" + matcher.group(2)); System.out.println("第 2 个分组内容[通过组名]=" + matcher.group("g2")); } } }4. 练习
要求如上 对字符串进行验证! 注意 汉字的编码如下范围 String regStr = "^[u0391-uffe5]+$";示例 package com.zhuang.regex; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @Classname Regex08 * @Description 应用实例 * @Date 2021/5/23 14:39 * @Created by dell */ public class Regex08 { public static void main(String[] args) { String content = "13588889999"; // 汉字 //String regStr = "^[u0391-uffe5]+$"; // 邮政编码 // 要求:是 1-9 开头的一个六位数. 比如:123890 // String regStr = "^[1-9]\d{5}$"; // QQ 号码 // 要求: 是 1-9 开头的一个(5 位数-10 位数) 比如: 12389 , 1345687 , 187698765 //String regStr = "^[1-9]\d{4,9}$"; // 手机号码 // 要求: 必须以 13,14,15,18 开头的 11 位数 , 比如 13588889999 String regStr = "^1[3|4|5|8]\d{9}$"; Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); if(matcher.find()) { System.out.println("满足格式"); } else { System.out.println("不满足格式"); } } }匹配URL的思路先确定 url 的开始部分 https:// | http://然后通过 ([w-]+.)+[w-]+ 匹配www.bilibili.com/video/BV1fh411y7R8?from=sear 匹配(/[w-?=&/%.#]*)?package com.zhuang.regex; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author dell * @Classname Regex09 * @Description 判断URL的表达式 * @Date 2021/5/23 14:42 * @Created by dell */ public class Regex09 { public static void main(String[] args) { //String content = "https://www.bilibili.com/video/BV1fh411y7R8?from=search&seid=1831060912083761326"; String content ="https://www.runoob.com/regexp/regexp-syntax.html"; //注意:[. ? *]表示匹配就是.本身 String regStr = "^((http|https)://)?([\w-]+\.)+[\w-]+(\/[\w-?=&/%.#]*)?$"; Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); if(matcher.find()) { System.out.println("满足格式"); } else { System.out.println("不满足格式"); } //这里如果使用 Pattern 的 matches 整体匹配 比较简洁 System.out.println(Pattern.matches(regStr, content));// } }5. 正则表达式常用的三个常用类
更多方法参考:Java 正则表达式 | 菜鸟教程 (runoob.com) package com.zhuang.regex; import java.util.regex.Pattern; /** * @Classname PatternMethod * @Description 演示 matches 方法,用于整体匹配, 在验证输入的字符串是否满足条件使用 * @Date 2021/5/23 14:49 * @Created by dell */ public class PatternMethod { public static void main(String[] args) { String content = "hello abc hello, kang"; //String regStr = "hello"; String regStr = "hello.*"; boolean matches = Pattern.matches(regStr, content); System.out.println("整体匹配= " + matches); } }Matcher类package com.zhuang.regex; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @Classname MatcherMethod * @Description Matcher常用方法 * @Date 2021/5/23 14:51 * @Created by dell */ public class MatcherMethod { public static void main(String[] args) { String content = "hello edu jack kangxiaohhh hello hhkxz hello kkxxaa kxzkxz"; String regStr = "hello"; Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); while (matcher.find()) { System.out.println("================="); System.out.println(matcher.start()); System.out.println(matcher.end()); System.out.println("找到: " + content.substring(matcher.start(), matcher.end())); } //整体匹配方法,常用于,去校验某个字符串是否满足某个规则 System.out.println("整体匹配=" + matcher.matches()); //完成如果 content 有 kang 替换成 康小庄!!! regStr = "kang"; pattern = Pattern.compile(regStr); matcher = pattern.matcher(content); //注意:返回的字符串才是替换后的字符串 原来的 content 不变化 String newContent = matcher.replaceAll("康小庄!!!"); System.out.println("newContent=" + newContent); System.out.println("content=" + content); } }6.分组,捕获,反向引用
分组可以用圆括号组成一个比较复杂的匹配模式,那么一个圆括号的部分我们可以看做是一个子表达式/一个分组捕获把正则表达式中子表达式/分组匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用,从左向右,以分组的左括号为标志,第一个出现的分组的组好为1,第二个位2,以此类推,组0代表的是整个正则式反向引用圆括号的内容被捕获后,可以在这个括号后使用,写出一个实用的匹配模式称为反向引用可以在表达式内部或者外部内部反向引用\分组号,外部反向引用的$分组号看几个案例 要匹配两个连续的相同数字(\d)\1要匹配五个连续的相同数字(\d)\1{4}要匹配个位与千位相同,十位与百位相同的数,5225,1551(\d)(\d)\2\1匹配 形如12321-333666999 这样的号码满足前面一个五位数 然后一个- 然后是一个九位数,连续的每三位要相同package com.zhuang.regex; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @Classname Regex10 * @Description 案例 * @Date 2021/5/23 15:26 * @Created by dell */ public class Regex10 { public static void main(String[] args) { String content="h23423288888856666 jackangdaxxxiiit6886 65432-999888777"; // 匹配连续两个相同的数字 // String regStr="(\d)\1"; // 匹配连续五个相同的数字 // String regStr="(\d)\1{4}"; //匹配 个位和千位相同 十位和百位相同的数字 // String regStr="(\d)(\d)\2\1"; // 匹配 形如12321-333666999 这样的号码满足前面一个五位数 // 然后一个- 然后是一个九位数,连续的每三位要相同 String regStr="\d{5}-(\d)\1{2}(\d)\2{2}(\d)\3{2}"; Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); while (matcher.find()){ System.out.println("找到->"+matcher.group(0)); } } }7.String 类中使用正则表达
替换功能 StringReg.java String 类 public String replaceAll(String regex,String replacement)判断功能 String 类 public boolean matches(String regex){} //使用 Pattern 和 Matcher 类分割功能 String 类 public String[] split(String regex)package com.zhuang.regex; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @Classname Regex11 * @Description String类中的方法 * @Date 2021/5/23 15:39 * @Created by dell */ public class Regex11 { public static void main(String[] args) { String content = "2000 年 5 月,JDK1.3、JDK1.4 和 J2SE1.3 相继发布,几周后其" + "获得了 Apple 公司 Mac OS X 的工业标准的支持。2001 年 9 月 24 日,J2EE1.3 发" + "布。" + "2002 年 2 月 26 日,J2SE1.4 发布。自此 Java 的计算能力有了大幅提升"; //使用正则表达式方式,将 JDK1.3 和 JDK1.4 替换成 JDK content = content.replaceAll("JDK1\.3|JDK1\.4", "JDK"); System.out.println(content); //要求 验证一个 手机号, 要求必须是以 138 139 开头的 content = "13888889999"; if (content.matches("1(38|39)\d{8}")) { System.out.println("验证成功"); } else { System.out.println("验证失败"); } //要求按照 # 或者 - 或者 ~ 或者 数字 来分割 System.out.println("==================="); content = "hello#abc-jack12smith~北京"; String[] split = content.split("#|-|~|\d+"); for (String s : split) { System.out.println(s); } } }8. 综合练习
8.1 验证电子邮件格式是否合法
只能有一个@ @前面是用户名,可以是a-z,A-Z,0-9 - _ 字符 @后面是域名 并且域名只能是英文字母 比如itkxz@qq.com 写出对应的正则表达式验证输入的字符串是否满足规则 先写出简单的表达式,再逐步完善! package com.zhuang.regex; /** * @Classname Homework01 * @Description 案例1 * @Date 2021/5/23 16:08 * @Created by dell */ public class Homework01 { public static void main(String[] args) { String content="itkxz@qq.com"; String regStr="[\w-_]+@([a-zA-Z]+\.)+[a-zA-Z]+"; if (content.matches(regStr)){ System.out.println("匹配成功!!!"); }else { System.out.println("匹配失败!!!"); } } }8.2 验证是不是整数或小数
考虑到正数和负数123 34.55 0.58等package com.zhuang.regex; /** * @Classname Homework01 * @Description 案例2 * @Date 2021/5/23 16:08 * @Created by dell */ public class Homework02 { public static void main(String[] args) { String content="-0.58"; String regStr="^[+-]?([1-9]\d*|0)(\.\d+)?$"; if (content.matches(regStr)){ System.out.println("匹配成功 是正数或者小数!!!"); }else { System.out.println("匹配失败!!!"); } } }8.3 验证是否为URL
协议域名端口文件名package com.zhuang.regex; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @Classname Homework03 * @Description 案例3 * @Date 2021/5/23 16:08 * @Created by dell */ public class Homework03 { public static void main(String[] args) { String content="http://space.bilibili.com:8080/abc/favlist"; String regStr="^([a-zA-Z]+)://([a-zA-Z.]+):(\d+)[\w-/]*/([\w.]+)$"; Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(content); if (matcher.matches()){ System.out.println("匹配成功!!!"); System.out.println("协议->"+ matcher.group(0)); System.out.println("域名->"+ matcher.group(1)); System.out.println("端口->"+ matcher.group(2)); System.out.println("文件名->"+ matcher.group(3)); }else { System.out.println("匹配失败!!!"); } }【Java正则表达式快速入门与实例解析】相关文章:
2.米颠拜石
3.王羲之临池学书
8.郑板桥轶事十则
用户评论
Java正则表达式真的很有用,尤其是在做数据处理的时候!
有19位网友表示赞同!
一直想学习,但总觉得太复杂了,这份笔记看起来很不错。
有19位网友表示赞同!
我以前只知道基本的用法,这篇笔记让我发现了更多技巧!
有14位网友表示赞同!
这个标题听着就专业 banget.
有18位网友表示赞同!
正则表达式确实是一个强大武器,掌握它能提高效率很多。
有13位网友表示赞同!
分享这篇文章的人也太贴心了,正好需要学习正则表达式。
有18位网友表示赞同!
希望笔记里有讲解一些常用的模式,那样就能直接用在项目开发中了。
有10位网友表示赞同!
我已经很久没接触过Java的代码了,这篇笔记能让我再熟悉一下语法。
有6位网友表示赞同!
我学计算机已经三年了,还没机会深入学习正则表达式,笔记看起来很详细。
有7位网友表示赞同!
笔记图片排版很清晰易懂,让人一看就明白。
有17位网友表示赞同!
正则表达式在编程中真是必不可少,要好好背熟这些常用模式!
有18位网友表示赞同!
感觉这篇笔记能解决我很多日常开发中的问题。
有12位网友表示赞同!
学习正则表达式的效率真高,掌握了这招就能轻松处理各种文本匹配问题。
有13位网友表示赞同!
Java真是很棒的语言,还有如此强大的工具辅助开发。
有14位网友表示赞同!
期待这篇笔记能让我快速入门正则表达式,加速开发进程!
有15位网友表示赞同!
正则表达式看起来很复杂,希望这篇笔记能用通俗易懂的方式讲解。
有14位网友表示赞同!
学习Java和Python的时候都没有好好学习正则表达式的用法,看来要补课啦 。
有16位网友表示赞同!
真希望能把这些例子加到我的代码练习中去! 提升实践能力!
有8位网友表示赞同!
我觉得学习正则表达式就像练武一样,需要不断地练习才能熟能生巧。
有7位网友表示赞同!