Java与正则表达式
2016-01-03 07:59
260 查看
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匹配类似
toto
dodo
gogo这样由一个单词复制而来得到的字符串
(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的异常、断言、日志和调试
- Java基本类型比较
- 第一节 麒麟系统安装+基础环境搭建(JDK+Scala)
- JavaMail介绍
- 比比Java和C#语言运行的快慢
- ?--Porg.springframework.beans.MethodInvocationException: Property 'username' threw exception; nested exception is java.lang.NullPointerException
- Java Web系列:Spring Security 基础
- Maven和Mybaties结合,Maven不处理java文件夹下面的配置文件
- java join用法
- Java中的代理模式
- Java开发中的23种设计模式详解
- java设计模式之学习
- java设计模式之单例模式
- leetcode 5:Longest Palindromic Substring 三种解法的java实现源代码,以及详细讲解
- 【转】Eclipse上安装GIT插件EGit及使用
- Java 创建多线程
- struts配置
- java设计模式学习
- 【15】Session
- 【14】Cookie