正则表达式
1.概述
在Java中,我们经常需要验证一些字符串,例如:年龄必须是2位的数字、用户名必须是8位长度而且只能包含大小写字母、数字等。正则表达式就是用来验证各种字符串的规则。它内部描述了一些规则,我们可以验证用户输入的字符串是否匹配这个规则。
2.字符类
语法示例:
[acbc]
:匹配a,b,c其中一个字符。[^abc]
:匹配除a,b,c以外的任何一个字符。[a-z]
:匹配a-z中的任何一个字符。[A-Z]
:匹配A-Z中的任何一个字符。[0-9]
:匹配0-9中的任何一个字符。[a-zA-Z0-9]
:匹配a-z或者A-Z或者0-9中的任何一个字符。[a-dm-p]
匹配a-d或者m-p中的任何一个字符。
3.逻辑运算符
语法示例:
&&
:并且|
:或者\
:转义字符
4.预定义字符
语法示例:
.
:匹配任意字符。\d
:匹配任意数字(等同于[0-9]
)。\D
:匹配任意非数字(等同于[^0-9]
)。\s
:匹配空白字符(等同于[\t\n\x0B\f\r]
)。\S
:匹配非空白字符(等同于[^\s]
)。\w
:匹配单词字符(等同于[a-zA-Z_0-9]
)。\W
:匹配非单词字符(等同于[^\w]
)。
5.数量词
语法示例:
x?
:匹配0次或1次(最多一次)。x*
:匹配0次或多次(任意次)。x+
:匹配1次或多次(至少一次)。x{n}
:匹配n次(恰好n次)。x{n,}
:匹配至少n次。x{n,m}
:匹配n到m次(至少n次,最多m次)。
6.汇总
符号 | 含义 | 举例 |
---|---|---|
[] | 里面的内容的其中之一出现一次 | [1-9] |
() | 分组 | a(bc)+ |
^ | 取反 | [^abc] |
&& | 交集 | [a-z&&m-p] |
| | 写在方括号外表示并集(方括号内可以省略) | x|X |
. | 任意字符(\n除外) | a.b |
\ | 转义符 | \\d |
\d | 数字([0-9]) | \\d+ |
\D | 非数字 | \\D+ |
\s | 空白字符([\t\n\x0B\f\r]) | \\s+ |
\S | 非空白字符 | \\S+ |
\w | 单词字符([a-zA-Z_0-9]) | \\w+ |
\W | 非单词字符 | \\W+ |
? | 0次或1次(最多1次) | \\d? |
* | 0次或多次(任意次) | \\d* |
+ | 1次或多次(至少1次) | \\d+ |
{} | 指定次数 | \\d |
(?i) | 忽略后面字符的大小写 | a((?i)b)c |
7.爬虫
7.1 本地数据爬取
Pattern
:表示正则表达式。
Matcher
:文本匹配器,按照正则表达式的规则去读取字符串。
代码示例:
String str = "Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台";
// 获取正则表达式对象
Pattern p = Pattern.compile("Java\\d{0,2}");
// 获取文本匹配器对象
Matcher m = p.matcher(str);
// 利用循环获取
while (m.find()) {
System.out.println(m.group());
}
7.2 网络数据爬取(了解)
需求:
把该网页中所有的身份证号码爬取出来。
代码示例:
URL url = new URL("http://list.chineseidcard.com/");
URLConnection connection = url.openConnection();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
String regex = "[1-9]\\d{16}(\\d|x|X)";
Pattern pattern = Pattern.compile(regex);
while ((line = bufferedReader.readLine()) != null) {
Matcher matcher = pattern.matcher(line);
while (matcher.find()) {
System.out.println(matcher.group());
}
}
7.3 按要求爬取
需求:
有如下文本,按要求爬取数据。
Java自从95年问世以来,经历了很多版本,目前企业中用的最多的是Java8和Java11,因为这两个是长期支持版本,下一个长期支持版本是Java17,相信在未来不久Java17也会逐渐登上历史舞台。
需求1:
爬取版本号为8,11.17的Java文本,但是只要Java,不显示版本号。
需求2:
爬取版本号为8,11,17的Java文本。正确爬取结果为:Java8 Java11 Java17 Java17
需求3:
爬取除了版本号为8,11,17的Java文本。
代码示例:
// 需求1:爬取版本号为8,11.17的Java文本,但是只要Java,不显示版本号。
String regex1 = "Java(?=8|11|17)";
// 需求2:爬取版本号为8,11,17的Java文本。正确爬取结果为:Java8 Java11 Java17 Java17
String regex2 = "Java(?:8|11|17)";
String regex3 = "Java(8|11|17)";
// 需求3:爬取除了版本号为8,11,17的Java文本。
String regex4 = "Java(?!8|11|17)";
7.4 贪婪爬取和非贪婪爬取
- 贪婪爬取:尽可能多地爬取数据。
- 非贪婪爬取:尽可能少地爬取数据。
使用方法:
- 贪婪爬取:只写
+
或*
- 非贪婪爬取:在
+
或*
后面加?
示例:
String text = "abbbbbbbbbbb";
String regex1 = "ab+"; // 结果:abbbbbbbbbbb
String regex2 = "ab+?"; // 结果:ab
String regex3 = "ab*";// 结果:abbbbbbbbbbb
String regex4 = "ab*?";// 结果:ab
8.String类中的相关方法
8.1 split
-
方法原型:
public String[] split(String regex)
-
代码示例:
String s = "小诗诗dqwefqwfqwfwq12312小丹丹dqwefqwfqwfwq12312小惠惠"; String[] arr = s.split("[\\w&&[^_]]+"); for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } /*输出: 小诗诗 小丹丹 小惠惠 */
8.2 replaceAll
-
方法原型:
public String replaceAll(String regex,String newStr)
-
代码示例:
String s = "小诗诗dqwefqwfqwfwq12312小丹丹dqwefqwfqwfwq12312小惠惠"; String result1 = s.replaceAll("[\\w&&[^_]]+", "vs"); System.out.println(result1); // 输出:小诗诗vs小丹丹vs小惠惠
9.捕获分组
规则:
只看左括号,不看右括号,按照左括号的顺序,从左往右,依次为第一组,第二组,第三组......
正则表达式内用\\组号
的形式使用,表达式外用$组号
的形式。
代码示例1:
//需求1:判断一个字符串的开始字符和结束字符是否一致?只考虑一个字符
//举例: a123a b456b 17891 &abc& a123b(false)
// \\组号:表示把第X组的内容再出来用一次
String regex1 = "(.).+\\1";
System.out.println("a123a".matches(regex1));
System.out.println("b456b".matches(regex1));
System.out.println("17891".matches(regex1));
System.out.println("&abc&".matches(regex1));
System.out.println("a123b".matches(regex1));
System.out.println("--------------------------");
//需求2:判断一个字符串的开始部分和结束部分是否一致?可以有多个字符
//举例: abc123abc b456b 123789123 &!@abc&!@ abc123abd(false)
String regex2 = "(.+).+\\1";
System.out.println("abc123abc".matches(regex2));
System.out.println("b456b".matches(regex2));
System.out.println("123789123".matches(regex2));
System.out.println("&!@abc&!@".matches(regex2));
System.out.println("abc123abd".matches(regex2));
System.out.println("---------------------");
//需求3:判断一个字符串的开始部分和结束部分是否一致?开始部分内部每个字符也需要一致
//举例: aaa123aaa bbb456bbb 111789111 &&abc&&
//(.):把首字母看做一组
// \\2:把首字母拿出来再次使用
// *:作用于\\2,表示后面重复的内容出现日次或多次
String regex3 = "((.)\\2*).+\\1";
System.out.println("aaa123aaa".matches(regex3));
System.out.println("bbb456bbb".matches(regex3));
System.out.println("111789111".matches(regex3));
System.out.println("&&abc&&".matches(regex3));
System.out.println("aaa123aab".matches(regex3));
代码示例2:
String str = "我要学学编编编编程程程程程程";
//需求:把重复的内容 替换为 单个的
//学学 学
//编编编编 编
//程程程程程程 程
// (.)表示把重复内容的第一个字符看做一组
// \\1表示第一字符再次出现
// + 至少一次
// $1 表示把正则表达式中第一组的内容,再拿出来用
String result = str.replaceAll("(.)\\1+", "$1");
System.out.println(result);
10.非捕获分组
分组之后不需要再用本组数据,仅仅是把数据括起来,非捕获分组不占用组号。
代码示例:
String regex = "[1-9]\\d{16}(?:\\d|x|X)";
标签:字符,12,Java,String,System,笔记,println,out
From: https://www.cnblogs.com/kuaicode/p/17163010.html