Java正则表达式学习笔记
为什么要学习正则表达式
。极速体验正则表达式威力
1.提取文章中所有的英文单词
2.提取文章中所有的数字
3.提取文章中所有的英文单词和数字
4.验证电子邮件
5.验证手机号
解决之道-正则表达式
1.为了解决上述问题,Java提供了正则表达式技术,专门用于处理类似文本问题
2.简单的说:正则表达式是对字符串执行模式匹配的技术
3.正则表达式:regular expression == regexp
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:快速体验正则表达式
* 作者:汤观林
* 日期:2022年01月10日 20时
*/
public class RegexpTest1 {
public static void main(String[] args) {
String context = "1995年,互联网的蓬勃发展给了Oak机会。业界为了使死板、单调的静态网页能够“灵活”起来,急需一种软件技术来开发一种程序," +
"这种程序可以通过网络传播并且能够跨平台运行。于是,世界各大IT企业为此纷纷投入了大量的人力、物力和财力。这个时候," +
"Sun公司想起了那个被搁置起来很久的Oak,并且重新审视了那个用软件编写的试验平台,由于它是按照嵌入式系统硬件平台体系结构进行编写的," +
"所以非常小,特别适用于网络上的传输系统,而Oak也是一种精简的语言,程序非常小,适合在网络上传输。Sun公司首先推出了可以嵌入网页" +
"并且可以随同网页在网络上传输的Applet(Applet是一种将小程序嵌入到网页中进行执行的技术),并将Oak更名为Java(在申请注册商标时," +
"发现Oak已经被人使用了,再想了一系列名字之后,最终,使用了提议者在喝一杯Java咖啡时无意提到的Java词语)。" +
"5月23日,Sun公司在Sun world会议上正式发布Java和HotJava浏览器。IBM、Apple、DEC、Adobe、HP、Oracle、Netscape和" +
"微软等各大公司都纷纷停止了自己的相关开发项目,竞相购买了Java使用许可证,并为自己的产品开发了相应的Java平台";
//1 提取文章中所有的英文单词
// 提取文章中所有的数字
// 提取文章中所有的英文单词和数字
//提取百度热榜 标题
//传统方法:遍历方式 代码量大 效率不高
//正则表达式方式
//1.1 先创建一个Pattern对象,模式对象,可以理解成就是一个正则表达式对象
Pattern pattern1 = Pattern.compile("[a-zA-Z]+");
Pattern pattern2 = Pattern.compile("[1-9]+");
Pattern pattern3 = Pattern.compile("([1-9]+)|([a-zA-Z]+)");
//1.2 再创建一个匹配器对象
//理解:就是matcher匹配器按照pattern模式,到content文本中去匹配
Matcher matcher = pattern3.matcher(context);
//1.3 可以开始循环匹配
while (matcher.find()){
//匹配内容,文本,放到m.group(0)
System.out.println("找到:"+matcher.group(0));
}
}
}
运行结果:
找到:1995
找到:Oak
找到:IT
找到:Sun
找到:Oak
找到:Oak
...
找到:HP
找到:Oracle
找到:Netscape
找到:Java
找到:Java
结论:
正则表达式-------文本处理的利器
大数据清洗数据
JDK的String类可以直接使用正则表达式
1.一个正则表达式,就是用某种模式去匹配字符串的一个公式。很多人因为它们看上去比较古怪而且复杂所以不敢去使用。
不过,经过练习后,就觉得这些复杂的表达式写起来还是相当简单的,而且,一旦你弄懂它们,你就能把数小时辛苦而且易错的
文本处理工作压缩在几分钟(甚至几秒钟)内完成。
2.老韩这里要强调,正则表达式不是只有Java才有,实际上很多编程语言都支持正则表达式进行字符串操作。
比如java,javascript,php。我们这里讲的是Java正则表达式。
Pattern对象时一个正则表达式对象,Pattern类没有公共构造方法。要创建一个Pattern对象,调用其公共静态方法,
它返回一个Pattern对象。该方法接受一个正则表达式作为它的第一个参数,
比如:Pattern pattertn = Pattern.compile(pattertn);
生成表达式对象
String regStr1 = "\\d+?";
Pattern pattern = Pattern.compile(regStr1); //生成表达式对象
整体匹配
boolean flag = Pattern.matches(regStr5, content5);
代码:
package com.tangguanlin.regexp;
import java.util.regex.Pattern;
/**
* 说明:Pattern的matches方法,用于整体匹配,在验证输入的字符串是否满足条件使用
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest10 {
public static void main(String[] args) {
String content5 = "hello abc hello,韩顺平教育";
String regStr5 = "hello";
boolean flag = Pattern.matches(regStr5, content5); //整体匹配
if (flag){
System.out.println("整体匹配");
}else {
System.out.println("整体不匹配");
}
}
}
运行结果:
整体不匹配
Matcher对象时对输入字符串进行解释和匹配的引擎。与Pattern类一样,Matcher也没有公共构造方法。
你需要调用Pattern对象的matcher方法来获得一个Matcher对象。
matcher.find():尝试查找与该模式匹配的输入序列的下一个子序列
String content = "hello111111 ok";
String regStr1 = "\\d+?";
Pattern pattern = Pattern.compile(regStr1);
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("匹配到:"+matcher.group(0));
}
matcher.matches():整体匹配
String content = "hello111111 ok";
String regStr1 = "\\d+?";
Pattern pattern = Pattern.compile(regStr1);
Matcher matcher = pattern.matcher(content);
boolean flag = matcher.matches(); //整体匹配
matcher.replaceAll("") 字符串替换
content = matcher.replaceAll("");
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:matcher.replaceAll的使用
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest12 {
public static void main(String[] args) {
String content = "我...我要...学学学学......编程Java!";
//1.去掉所有的.
Pattern pattern = Pattern.compile("\\.");
Matcher matcher = pattern.matcher(content);
content = matcher.replaceAll("");
System.out.println(content);
}
}
运行结果:
我我要学学学学编程Java!
PatternSyntaxException是一个非强制异常类,它表示一个正则表达式模式的语法错误。
如果想灵活的运用正则表达式,必须了解其中各种元字符的功能,
元字符从功能上大致分为:
1.限定符
2.选择匹配符
3.分组组合和反向引用符
4.特殊字符
5.字符匹配符
6.定位符
7.转义符号 \ \
转义符号 \ \
说明:在我们使用正则表达式去检索某些特殊字符的时候,需要用到转义符号,
否则检索不到结果,甚至会报错的。
再次提示:在Java的正则表达式中,两个\ \代表其他语言中的一个\
Java中的转义是2个\
需要用到转义符号的字符有以下: . * + ( ) $ / \ ? [ ] ^ { }
比如:用 去 匹 配 “ a b c 去匹配“abc 去匹配“abc("会怎样?
用(去匹配“abc$(”会怎样?
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:转义字符的验收
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest2 {
public static void main(String[] args) {
String content ="abc$(";
String reg = "\\(";
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("找到:"+matcher.group(0));
}
}
}
运行结果:
找到:(
注意:[.]表示匹配就是.本身
语法:
符号 | 符号含义 | 示例 | 示例含义 | 匹配输入 |
---|---|---|---|---|
[] | 可接受的字符列表 | [efgh] | e、f、个、h中的任意1个字符 | |
[^] | 不可接受的字符列表 | [^abc] | 除a、b、c之外的任意1个字符,包括数字和特殊符号 | |
- | 连字符 | A-Z | 任意单个大写字母 | |
. | 匹配除\n以外的任何字符 | a…b | 以a开头,b结尾,中间包含2个任意字符的长度为4的字符串 | aaab、aefb、a35b、a#*b |
\ \d | 匹配单个数字字符,相当于[0-9] | \ \d{3}(\ \d)? | 包含3个或4个数字的字符串 | 123、9876 |
\ \D | 匹配单个非数字字符,相当于[ ^1-9 ] | \ \D(\ \d)* | 以单个非数字字符开头,后接任意个数字字符串 | a、A342 |
\ \w | 匹配单个数字,大小写字母,字符,相当于[0-9a-zA-Z] | \ \d{3}\ \w{4} | 以3个数字字符开头的长度为7的数字字母字符串 | 123abcd、12345pe |
\ \W | 匹配单个非数字,大小写字母字符,相当于[ ^0-9a-zA-Z] | \ \w+\ \d{2} | 以至少1个非数字字母字符开头,2个数字字符结尾的字符串 | #29、#?@10 |
应用实例:
1.[a-z]说明:
[a-z]表示可以匹配a-z中任意一个字符,比如[a-z]、[A-Z]去匹配a11c8会得到说明结果?
2.java正则表达式默认是区分字母大小写的,如何实现不区分大小写
。(?i)abc 表示abc都不区分大小写
。a(?i)bc 表示bc不区分大小写
。a((?i)b)c 表示只有b不区分大小写
。Pattern pat = Pattern.compile(regEx,Pattern.CASE_INSENSITIVE);
[0-9]表示可以匹配0-9中任意一个字符。
4.[abcd]表示可以匹配abcd中任意一个字符。
5.[ ^abcd]表示可以匹配不是abcd中的任意一个字符。
当然上面的abcd你可以根据实际情况修改,以适应你的需求
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:演示字符匹配符的使用
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest3 {
public static void main(String[] args) {
String content = "a11c8abcABC";
//String regStr = "[a-z]"; //匹配a到z之间的任意一个字符
//String regStr = "[A-Z]"; //匹配A到Z之间的任意一个字符
String regStr = "abc"; //匹配abc 默认区分大小写
Pattern pattern = Pattern.compile(regStr,Pattern.CASE_INSENSITIVE); //不区分大小写
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("匹配到:"+matcher.group(0));
}
}
}
选择匹配符: 在匹配某个字符串的时候是选择性的,“或” 关系
即:既可以匹配这个,又可以匹配那个,这时你需要用到选择匹配符 |
符号 | 符号含义 | 示例 | 示例含义 |
---|---|---|---|
| | 匹配“|”之前或之后的表达式 | ab|cd | ab或cd |
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:选择匹配符
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest4 {
public static void main(String[] args) {
String content = "hanshunping 韩 寒冷";
String regStr = "han|韩|寒"; //选择匹配符
Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("匹配到:"+matcher.group(0));
}
}
}
运行结果:
匹配到:han
匹配到:韩
匹配到:寒
限定符: 用于指定其前面的字符和组合项连续出现多少次 ? + * {3}
注意:java匹配默认贪婪匹配:尽可能匹配多的
符号 | 符号含义 | 示例 | 示例含义 | 匹配输入 |
---|---|---|---|---|
? | 指定字符出现0次或1次(最多1次) | m+abc? | 以至少1个m开头,后接ab或abc的字符串 | mab、mabc、mmmab、mmabc |
+ | 指定字符重复1次或n次(至少1次) | m+(abc)* | 以至少1个m开头,后接任意个abc的字符串 | m、mabc、mabcabc |
* | 指定字符重复0次或n次(无要求) | (abd)* | 仅包含任意个abc的字符串,等效于\w* | abc、abcabcabc |
{n} | 只能输入n个字符 | [abcd]{3} | 由abcd中字母组成的任意长度为3的字符串 | abc、dbc、adc |
{n,} | 指定至少n个匹配 | [abcd]{3,} | 由abcd中字母组成的任意长度不小于3的字符串 | aab、dbc、aaabdc |
{n,m} | 指定至少n个但不多于m个匹配 | [abcd]{3,5} | 由abcd中字母组成的任意长度不小于3,不大于5的字符串 | abc、abcd、aaaaa、bcdab |
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:限定匹配符
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest5 {
public static void main(String[] args) {
String content = "1111111aaahello";
String regStr1 = "a{3}"; //表示匹配 aaa 匹配到:aaa
String regStr2 = "1{4}"; //表示匹配 1111 匹配到:1111
String regStr3 = "\\d{2}"; //表示匹配 两位的任意数字字符 匹配到:11 匹配到:11 匹配到:11
Pattern pattern = Pattern.compile(regStr3);
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("匹配到:"+matcher.group(0));
}
}
}
运行结果:
匹配到:11
匹配到:11
匹配到:11
定位符:规定要匹配的字符串出现的位置,
比如在字符串的开始还是在结束的位置,这个也是相当有用的。
符号 | 符号含义 | 示例 | 示例含义 | 匹配输入 |
---|---|---|---|---|
^ | 指定起始字符 | 1+[a-z]* | 以至少1个数字开头,后接任意个小写字母的字符串 | 123、6aa、555edf |
$ | 指定结束字符 | 2\ -[a-z]+$ | 以1个数字开头后接连字符“_”,并以至少1个小写字母结尾的字符串 | 1-a |
\ \b | 匹配边界的字符串 | han\ \b | 这里说的字符串的边界指的是子串间有空格,或者是目标字符串的结束位置 | hanshunpingsphan nnhan |
\ \B | 匹配非边界的字符串 | han\ \B | 和\ \b的含义刚刚相反 | hanshunpingsphan nnhan |
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:定位符的使用
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest6 {
public static void main(String[] args) {
String content = "123_abc";
//以至少1个数字开头,必须以至少1个小写字母结尾
String regStr1 = "^[0-9]+\\_[a-z]+$";
Pattern pattern = Pattern.compile(regStr1);
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("匹配到:"+matcher.group(0));
}
}
}
运行结果:
匹配到:123_abc
例子:
1.汉字
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:汉子
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest9 {
public static void main(String[] args) {
//汉字
String content = "韩顺平教育";
String regStr1 = "^[\u0391-\uffe5]+$";
Pattern pattern = Pattern.compile(regStr1);
Matcher matcher = pattern.matcher(content);
if (matcher.find()){
System.out.println("满足格式");
}
}
}
运行结果:
满足格式
2.邮政编码
要求:是1-9开头的一个六位数 比如:123890
String content2 = "123890";
String regStr2 = "^[1-9][0-9]{5}$";
3.QQ
要求:是1-9开头的一个5到10位数 数字
String content3 = "258921444";
String regStr3 = "^[1-9][0-9]{4,9}$";
4.手机号码
要求:必须以13,14,15,18开头的11位数,比如 13588889999
String content4 = "13588889999";
String regStr4 = "^1[3458][0-9]{9}$";
5.URL
String content5 = "https://www.bilibili.com/video/BV1fh411y7R8?from=search&seid=1831060912083761326";
String content6 = "https://live.bilibili.com/21395132? ·
hotRank=0&session_id=7c3539e60ecaf665700b4f7ae15374e2_02A1101E-A20D-43E4-BFE7- 57D2F32ADA2A&launch_id=1000217&spm_id_from=333.851.b_62696c695f7265706f72745f6c697665.5";
String regStr5 = "^((http|https)://)([\\w-]+\\.)+[\\w-]+(\\/[\\w-?=&/%.#]*)?$";
符号 | 符号含义() |
---|---|
? | 最小匹配,当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 “oooo”,‘o+?’ 将匹配单个 “o”,而 ‘o+’ 将匹配所有 ‘o’。 |
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:非贪婪匹配
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest8 {
public static void main(String[] args) {
String content = "hello111111 ok";
String regStr1 = "\\d+?"; //非贪婪匹配
Pattern pattern = Pattern.compile(regStr1);
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("匹配到:"+matcher.group(0));
}
}
}
运行结果:
匹配到:1
匹配到:1
匹配到:1
匹配到:1
匹配到:1
匹配到:1
分组:我们可以用()组成一个比较复杂的匹配模式,那么一个()的部分我们可以看作是一个分组/子表达式
符号 | 符号含义() |
---|---|
(正则表达式) | 非命名捕获。捕获匹配的子字符串。编号为0的第一个捕获是由整个正则表达式模式匹配的文本,其他捕获结果则根据左括号的顺序从1开始自动编号。 |
(?正则表达式) | 命名捕获。将匹配的子字符串捕获到一个组名称或者编号名称中。用于name的字符串不能包含任何标点符号,并且不能以数字开头。可以使用单引号替代尖括号,例如(?‘name’) |
捕获:把正则表达式中分组匹配的内容,保存到内存中,以数字编号或者显式命名的组里,方便后面引用。
从左向右,以分组的左括号为标志,
第一个出现的分组的组号为1,
第二个出现的分组的组号为2,以此类推。
组0代表的是整个正则式
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:分组+捕获
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest7 {
public static void main(String[] args) {
String content = "hanshunping s7789 nn1189han";
/**
* 1.matcher.group(0) 得到匹配到的字符串
* 2.matcher.group(1) 得到匹配到的字符串的第1个分组内容
* 3.matcher.group(2) 得到匹配到的字符串的第2个分组内容
*/
String regStr1 = "(\\d\\d)(\\d\\d)"; //匹配2个数字的字符串
Pattern pattern = Pattern.compile(regStr1);
Matcher matcher = pattern.matcher(content);
while (matcher.find()){
System.out.println("匹配到:"+matcher.group(0));
System.out.println("第1个分组:"+matcher.group(1));
System.out.println("第2个分组:"+matcher.group(2));
}
}
}
运行结果:
匹配到:7789
第1个分组:77
第2个分组:89
匹配到:1189
第1个分组:11
第2个分组:89
反向引用:()的内容被捕获后,可以在这个括号后被使用,从而写出一个比较实用的匹配模式,
这个我们成为反向引用,
这种引用既可以是在正则表达式内部,内部反向引用 \ \分组号
也可以是在正则表达式外部, 外部反向引用 $分组号
反向引用 很有用
例子:
1.要匹配两个连续的相同的数字
(\\d)\\1
2.要匹配五个连续的相同的数字
(\\d)\\1{4}
3.要匹配个位和千位相同,十位与百位相同的数字 比如:5225,1551
(\\d)(\\d)\\2\\1
4.请在字符串中检索商品编号,形式如:12321-333999111这样的号码,
要求满足前面是一个五位数,然后一个-号,然后是一个九位数,连续的每三位要相同
\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:反向引用
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest11 {
public static void main(String[] args) {
String content5 = "hello12321-333999111hanshunpinghello";
String regStr5 = "\\d{5}-(\\d)\\1{2}(\\d)\\2{2}(\\d)\\3{2}";
Pattern pattern = Pattern.compile(regStr5);
Matcher matcher = pattern.matcher(content5);
if (matcher.find()){
System.out.println("找到"+matcher.group(0));
}
}
}
运行结果:
找到12321-333999111
5.经典的结巴程序
把类似:“我…我要…学学学学…编程Java!”,通过正则表达式修改成 “我要学编程Java”
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:经典的结巴程序
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest12 {
public static void main(String[] args) {
String content = "我...我要...学学学学......编程Java!";
//1.去掉所有的.
Pattern pattern = Pattern.compile("\\.");
Matcher matcher = pattern.matcher(content);
content = matcher.replaceAll("");
System.out.println(content);
//2.去掉重复的字 我要学学学学编程Java!
//2.1 使用(.)\\1+
//2.2 使用 反向引用$1 来替换 匹配的内容
pattern = Pattern.compile("(.)\\1+");
matcher = pattern.matcher(content);
content = matcher.replaceAll("$1");
System.out.println(content);
//3.使用一条语句 去掉重复的字
String content1 = "我...我要...学学学学......编程Java!";
content1 = Pattern.compile("(.)\\1+").matcher(content).replaceAll("$1");
System.out.println(content1);
}
}
运行结果:
我我要学学学学编程Java!
我要学编程Java!
我要学编程Java!
语法: str.replaceAll(regStr,“JDK”)
//将JDK1.3 JDK1.4统一改为JDK
String content = content.replaceAll("JDK1.3|JDK1.4", "JDK");
语法:str.matches(regStr)
content = "13688889999";
boolean flag = content.matches("1(36|39)\\d{8}");
语法:str.split(reg);
content = "hello#abc-jack12smith~北京";
String[] str = content.split("#|-|\\d+|~");
代码:
package com.tangguanlin.regexp;
import java.util.Arrays;
/**
* 说明:String类使用正则表达式:替换+判断+分割
* 作者:汤观林
* 日期:2022年01月12日 00时
*/
public class StringReg {
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的计算能力有了大幅提升";
//1.替换
//使用正则表达式 将JDK1.3 JDK1.4替换为 JDK
content = content.replaceAll("JDK1.3|JDK1.4", "JDK");
System.out.println(content);
//2.判断
//要求:验证一个手机号,要求必须是136 139开头的11个数字
content = "13688889999";
boolean flag = content.matches("1(36|39)\\d{8}");
if(flag){
System.out.println("验证成功");
}
//3.分割
//要求: 按照# 或者 - 或者 ~ 或者数字 来分隔
content = "hello#abc-jack12smith~北京";
String[] str = content.split("#|-|\\d+|~");
System.out.println(Arrays.toString(str));
}
}
运行结果:
2000年5月,JDK、JDK和J2SE1.3相继发布,几周后其获得了Apple公司Mac OS X的工业标准的支持。2001年9月24日,J2EE1.3发布。2002年2月26日,J2SE1.4发布。自此Java的计算能力有了大幅提升
验证成功
[hello, abc, jack, smith, 北京]
规定电子邮件规则为:
(1)只能有一个@
(2)@前面是用户名,可以是a-zA-Z0-9 _ -字符
(3)@后面是域名,并且域名只能是英文字母,比如souhu.com
写出对应的正则表达式,验证输入的字符串是否为满足规则
^[\\w-]+@([a-zA-Z]+\\.)+[a-zA-Z]+$
提示:这个要考虑正数和负数
比如:123, -345 ,34.8,-87.9,-0.01, 0.45等
^[+-]?([1-9]\\d*|0)(\\.\\d+)?$
http://www.sohu.com:8080/abc/index.htm
(1)要求得到协议是什么 http
(2)域名是什么 www.sohu.com
(3)端口是什么 8080
(4)文件名是什么 index.htm
^([a-zA-Z]+)://([a-zA-Z.]+):(\d+)[\w-/]*/([\w.]+)$
代码:
package com.tangguanlin.regexp;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 说明:解析url
* 作者:汤观林
* 日期:2022年01月11日 00时
*/
public class RegexpTest13 {
public static void main(String[] args) {
String content = "http://www.sohu.com:8080/abc/index.htm";
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("整体匹配:"+matcher.group(0));
System.out.println("协议:"+matcher.group(1));
System.out.println("域名:"+matcher.group(2));
System.out.println("端口:"+matcher.group(3));
System.out.println("文件:"+matcher.group(4));
}
}
}
运行结果:
整体匹配:http://www.sohu.com:8080/abc/index.htm
协议:http
域名:www.sohu.com
端口:8080
文件:index.htm
常用的Java正则表达式:
校验数字的表达式
数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$
正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的负整数:^\-[1-9][]0-9″*$ 或 ^-[1-9]\d*$
非负整数:^\d+$ 或 ^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$
校验字符的表达式
汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
长度为3-20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&',;=?$\”等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~\x22]+
特殊需求表达式
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
InternetURL:[a-zA-z]+://[^\s]* 或 ^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
电话号码(“XXX-XXXXXXX”、”XXXX-XXXXXXXX”、”XXX-XXXXXXX”、”XXX-XXXXXXXX”、”XXXXXXX”和”XXXXXXXX):^($$\d{3,4}-)|\d{3.4}-)?\d{7,8}$
国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
身份证号(15位、18位数字):^\d{15}|\d{18}$
短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$
xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正则表达式:[\u4e00-\u9fa5]
双字节字符:[^\x00-\xff] (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
空白行的正则表达式:\n\s*\r (可以用来删除空白行)
HTML标记的正则表达式:<(\S*?)[^>]*>.*?\1>|<.*? /> (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$) (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
腾讯QQ号:[1-9][0-9]{4,} (腾讯QQ号从10000开始)
中国邮政编码:[1-9]\d{5}(?!\d) (中国邮政编码为6位数字)
IP地址:\d+\.\d+\.\d+\.\d+ (提取IP地址时有用)
IP地址:((25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}\2
钱的输入格式
有四种钱的表示形式我们可以接受:”10000.00″ 和 “10,000.00″, 和没有 “分” 的 “10000″ 和 “10,000″:^[1-9][0-9]*$
这表示任意一个不以0开头的数字,但是,这也意味着一个字符”0″不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$
一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$
这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$
必须说明的是,小数点后面至少应该有1位数,所以”10.”是不通过的,但是 “10″ 和 “10.2″ 是通过的:^[0-9]+(.[0-9]{2})?$
这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$
这样就允许用户只写一位小数。下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$
1到3个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$
备注:这就是最终结果了,别忘了”+”可以用”*”替代。如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
0-9 ↩︎
0-9 ↩︎