Java与正则表达式
Java与正则表达式
标签: Java基础
正则
正如
正则的名字所显示的是描述了一个规则, 通过这个规则去匹配字符串. 学习正则就是学习正则表达式的语法规则
正则语法
普通字符
字母, 数字, 汉字, 下划线, 以及没有特殊定义的标点符号都是普通字符. 表达式中的普通字符在匹配一个字符串时, 匹配与之相同的一个字符.
转义字符
| 字符 | 解释 |
|---|---|
\n |
换行符 |
\t |
制表符 |
\^ \$ \( \) \{ \} \? \+ \* | \\ \[ \] |
匹配这些字符本身 |
标准字符集合
| 字符 | 匹配 |
|---|---|
\d |
任意一个数字 |
\w |
任意一个字母/数字/下划线 |
\s |
任意一个空格/制表符/换行符等空白字符 |
. |
小数点在内的任意一个字符(除\n外) |
[\s\S] |
匹配\n在内的任意一个字符 |
- 注意大小写: 大写是取反
自定义字符集合
[] 方括号匹配方式, 能够匹配方括号中的任意一个字符.
| 表达式 | 解释 |
|---|---|
[ab5@v] |
匹配a b 5 @ v中任意一个 |
[^ab5@v] |
匹配a b 5 @ v之外任意一个 |
[f-k] |
匹配f-k之间任意一个字母 |
[^f-k] |
匹配f-k之外任意一个 |
[f-k0-3] |
匹配f-k或0-3之间任意一个字母 |
[^f-k0-3] |
不匹配f-k或0-3之间任意一个字母 |
注:
- 正则表达式中的特殊符号, 被包含到
[]中, 则失去特殊意义, 除了-^之外.[]中的^表示取反的含义.[]中的-表示范围的含义
- 标准字符集合(除小数点外),如果被包含于中括号中,则自定义集合将包含该集合.
如[\d.\-+]将匹配: 数字, 小数点,-,+
量词
| 量词 | 解释 |
|---|---|
{n} |
表达式重复n次 |
{m,n} |
表达式至少重复m次,最多重复n次 |
{m,} |
表达式至少重复m次 |
? |
匹配表达式0次或者1次 |
+ |
表达式至少出现1次,相当于 {1,} |
* |
表达式不出现或出现任意次,相当于 {0,} |
贪婪模式与非贪婪模式
贪婪模式: 匹配字符越多越好,默认.
非贪婪模式: 匹配字符越少越好, 需要在量词后再加上一个?号.示例
- 匹配手机号
1[358]\d{9} - 匹配邮箱
([\w\-\.]+)@([0-9a-zA-Z\-]+)(\.[a-zA-Z]{2,4}){1,2}
- 匹配手机号
字符边界
零宽匹配: 匹配的不是字符而是位置(符合某种条件的位置),不匹配任何字符.
| 字符 | 解释 |
|---|---|
^ |
与字符串开始的地方匹配 |
$ |
与字符串结束的地方匹配 |
\b |
匹配一个单词边界,也就是单词和空格之间的位置 |
注: \b会匹配这样一个位置: 前面的字符与后面的字符不全是\w
选择符与分组
| 表达式 | 解释 |
|---|---|
| |
左右两边表达式之间 “或” 关系,匹配左边或右边 |
() 捕获组 |
被修饰时,()中的表达式可以作为整体被修饰; 取匹配结果时, ()中的表达式匹配到的内容可以被单独得到; 每一对括号会被分配一个编号(以(为准,从左到右: 从1开始) |
(?:exp) 非捕获组 |
一些表达式中, 不得不使用(), 但又不需保存()中子表达式匹配的内容, 这时可以使用非捕获组来抵消()带来的副作用 |
注: 非捕获组可以用于当处理大量文本时用于优化内存分配.
- 反引用
\nnn
由上面可知, 捕获组默认被分配了编号, 通过反向引用, 可以对分组已捕获的字符串进行引用 - 示例
(\w{2})\1匹配类似totododogogo这样由一个单词复制而来得到的字符串
(img)\w+\1匹配前后都是img的字符串
零宽断言(预搜索)
- 零宽度: 只进行子表达式的匹配, 匹配内容不计入最终的匹配结果.
- 位置匹配: 判断当前位置的前后字符是否符合指定的条件, 但不保留前后的字符.
正则表达式中, 如果子表达式匹配到得是字符内容, 而非位置, 并被保留到最终的匹配结果中, 那么就认为这个子表达式是
占有字符的; 如果子表达式匹配的仅仅是位置, 或者匹配的内容并不保存到最终的匹配结果中, 那么就认为这个子表达式是零宽度的(占有字符或零宽度, 是针对匹配的内容是否保留到最终结果而言的)
| 表达式 | 解释 |
|---|---|
(?=exp) |
断言自身出现的位置的后面能够匹配表达式exp |
(?!exp) |
断言自身出现的位置的后面不能匹配表达式exp |
(?<=exp) |
断言自身出现的位置的前面能够匹配表达式exp |
(?<\!exp) |
断言自身出现的位置的前面不能匹配表达式exp |
- 示例
[a-z]+(?=ing)匹配所有以ing结尾的单词, 但ing并不放入字符串
[a-z]+(?=\d+)匹配所有以数字结尾的单词
[a-z]+(?!\d+)匹配不以数字结尾的单词
(?<=(href=\"))匹配以href="开头的字符串
Java Pattern与Matcher
java.util.regex包下提供的Pattern与Matcher两个类提供了在Java中的正则支持;Pattern对象是正则表达式编译后在内存中的表现形式, 因此, 正则表达式字符串必须先被编译为Pattern对象Pattern pattern = Pattern.compile("\\w+");然后再利用该Pattern对象创建对象的Matcher对象Matcher matcher = pattern.matcher(input);.Matcher对象是一个对CharSequence执行匹配操作的正则引擎: 执行匹配所涉及的状态保留在Matcher对象中, 多个Matcher对象可共享同一个Pattern对象.
/**
* Created by jifang on 15/12/15.
*/
public class LearnRegexp {
@Test
public void testSearch() {
String input = "hello1997&&2000";
// 将一个正则表达式编译成Pattern对象
Pattern pattern = Pattern.compile("\\w+");
Matcher matcher = pattern.matcher(input);
// matches尝试将整个字符序列与该模式匹配
System.out.println(matcher.matches());
// reset将matcher中的指针重新定位
matcher.reset();
// find 方法扫描整个字符串, 查找能否找到下一个符合该模式字符串
while (matcher.find()) {
String group = matcher.group();
System.out.println(group);
}
}
/**
* 将所有的数字都替换成'#'
*/
@Test
public void testReplace() {
String input = "1j2h3h4g5o";
Matcher replace = Pattern.compile("[0-9]").matcher(input);
input = replace.replaceAll("#");
System.out.println(input);
}
/**
* 将字符串按数字分割
*/
@Test
public void testSplit() {
String input = "1j24h356h467g589o";
String[] strings = input.split("\\d+");
for (String str : strings) {
System.out.println(str);
}
}
}
由上例可以看到: 其实String中某些方法也支持正则表达式, 如split, replace等(Pattern,Matcher与String的其他用法请参考JDK文档).
小实验-抓取网页中所有的超链接
/**
* 模仿网络爬虫, 抓取网站html, 将里面所有的超链接都分析出来
* Created by jifang on 15/12/15.
*/
public class HtmlAnalyzer {
private final String FILE_PATH = "/Users/jifang/save.txt";
@Test
public void client() throws IOException {
String html = downloadHtml("http://www.163.com/", "gbk");
// (?<=(href=\"))(?:[\w.\/\:\?\=\&]+)(?=\") 匹配url的正则
Set<String> urlSet = analyzeHtml(html, "(?<=(href=\\\"))(?:[\\w.\\/\\:\\?\\=\\&]+)(?=\\\")");
saveToFile(urlSet);
System.out.println();
}
private String downloadHtml(String url, String charset) throws IOException {
URL readUrl = new URL(url);
BufferedReader reader = new BufferedReader(new InputStreamReader(readUrl.openStream(), charset));
return CharStreams.toString(reader);
}
private Set<String> analyzeHtml(String html, String regex) {
Set<String> urlSet = new HashSet<>();
// 匹配url的正则表达式
Matcher matcher = Pattern.compile(regex).matcher(html);
while (matcher.find()) {
String group = matcher.group();
urlSet.add(group);
}
return urlSet;
}
private void saveToFile(Set<String> urlSet) throws IOException {
PrintStream printer = new PrintStream(new FileOutputStream(FILE_PATH));
for (String url : urlSet) {
printer.println(url);
}
printer.flush();
printer.close();
}
}
- 附- 运行上程序需要在pom.xml中添加以下依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
推荐几个正则验证工具:
- Mac端: RegExRX
- Win端: RegexBuddy
- Web端: 在线正则表达式测试
参考
Java与正则表达式的更多相关文章
- java中正则表达式基本用法
正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它 用以描述在查找文字主体时待匹配的一个或多个字符串.正则表达式作为 ...
- java基础---->java中正则表达式二
跟正则表达式相关的类有:Pattern.Matcher和String.今天我们就开始Java中正则表达式的学习. Pattern和Matcher的理解 一.正则表达式的使用方法 一般推荐使用的方式如下 ...
- Java的正则表达式
package RegexTest; /** * Created by hu on 2016/3/29. */ /* * Java的正则表达式 在正则表达式中,用\d表示一位数字,如果在其它语言中使用 ...
- Java中正则表达式去除html标签
Java中正则表达式去除html的标签,主要目的更精确的显示内容,比如前一段时间在做类似于博客中发布文章功能,当编辑器中输入内容后会将样式标签也传入后台并且保存数据库,但是在显示摘要的时候,比如显示正 ...
- Java面向对象 正则表达式
Java面向对象 正则表达式 知识概要: (1)正则表达式的特点 (2)正则表达的匹配 (3)正则表达式的切割,替换,获取 (4)正则表达式的练习 正则表达式:符合 ...
- Java 常用正则表达式,Java正则表达式,Java身份证校验,最新手机号码正则表达式
Java 常用正则表达式,Java正则表达式,Java身份证校验,最新手机号码校验正则表达式 ============================== ©Copyright 蕃薯耀 2017年11 ...
- JAVA中正则表达式常用的四个方法
JAVA中正则表达式处理字符串的四个常用方法:匹配.分割.替换.截取.其跟字符串的常用函数相似,但是使用正则表达式会更简单.更加简洁.下面是具体的例子: public class TestRegex ...
- Java对正则表达式的支持(一)
Java对正则表达式的支持主要体现在String.Pattern.Matcher和Scanner类. 1.Pattern.Matcher 先看一个Pattern和Matcher类使用正则表达式的例子. ...
- Java中用正则表达式判断日期格式是否正确
1.Java中用正则表达式判断日期格式是否正确 DateType.java: /** * @Title:DateType.java * @Package:com.you.dao * @Descript ...
随机推荐
- Eclipse 项目管理控制软件svn
^_^太开心了,之前以为eclipse只有tortoiseSVN而没有类似Visual Studio 2010里面的cvs的版本控制软件,不是我讨厌tortoiseSVN,而是我实在不习惯使用这个软件 ...
- android studio 中设置apk的版本号
今天在mainfest.xml中设置版本号为2,(代码获取到的版本号无效) android:versionCode="2" android:versionName="2. ...
- firefox常用扩展、脚本
1.AutoPopup.uc.js:鼠标移到菜单和下拉箭头上自动弹出下拉菜单 2.moveButton.uc.js:移动或克隆按钮或菜单到火狐浏览器的任意位置 moveButton.uc.js使用说明 ...
- Codeforces Round #311 (Div. 2) D. Vitaly and Cycle 奇环
题目链接: 点这里 题目 D. Vitaly and Cycle time limit per test1 second memory limit per test256 megabytes inpu ...
- 奇异值分解(We Recommend a Singular Value Decomposition)
奇异值分解(We Recommend a Singular Value Decomposition) 原文作者:David Austin原文链接: http://www.ams.org/samplin ...
- Google 网站打不开
http://209.116.186.246/ http://91.213.30.153/ (2014年6月30日 新增) https://wen.lu/ (2014年6月30日 新增,注意下是ht ...
- java reflect 例子
public static void main(String[] args) { Student stu1 = new Student(); stu1.setId(1); stu1.setName(& ...
- c# Invoke和BeginInvoke 区别
原文:http://www.cnblogs.com/mashang/archive/2009/08/01/1536730.html Control.Invoke 方法 (Delegate) :在拥有此 ...
- mac os 下如何清除/切换svn eclipse插件的用户
以mac os x为例(Unix/Linux类似), 1.打开命令行窗口,即用户的根目录(用户的home目录) $ ls -al ... drwxr-xr-x 6 linxyz staff ...
- [LeetCode]Link List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...