鱼喃

听!布鲁布鲁,大鱼又在那叨叨了

正则表达式(3)----在Java里的使用

从Java 1.4.0 开始,Java就内建了正则表达式包,java.util.regex,它使用的是传统型NFA。

通过java.util.regex 使用正则表达式非常简单,功能由一个接口(MatchResult)、两个类(Matcher、Pattern)、一个异常(PatternSyntaxException)组成。

Pattern是编译好的正则表达式,可以应用到多个实现了CharSequence接口的对象(String、StringBuffer、StringBuilder、CharBuffer等)上,而matcher则是对应具体的实例,表示将正则表达式应用到某个具体的目标字符串上。

本文通过编写一个从网页源代码中提取网络图片地址和转义标签(就是把“<”、“>”转换成“&lt;”、“&gt;”,写过web代码的朋友都懂)的Java实例来学习Java中的正则表达式的使用。

提取网络图片地址

首先,构造正则表达式。我们预期的的地址模式是类似于http://img.newnius.com/upload/201505180010.png 这种格式,支持https,支持自定义端口号,支持png、jpg、gif这三种图片格式。简单构造,得到以下正则表达式:https?://[_a-z0-9]+(\.[_a-z0-9]+)+(:[0-9]+)?/( [_a-z0-9]+/)*(png|jpg/gif),这样看起来有点长,可以用到Java里的其他元字符,比如“/w”这个表示一般的字符,等价于[a-zA-Z_0-9],另外,考虑到我们并不需要捕获其中的分组,用(?:)来表示不需要捕获。这两种方式可以加快正则表达式的远行速度。最终的正则表达式是这样的:https?://\\w+(?:\\.\\w+)+(?::\\d+)?/(?:\\w+/)*\\w+\\.(?:png|jpg|gif)。(Java里“\”需要写成“\\”形式,所以原始的正则表达式里的“\”全部要变成“\\”,这是由于Java会对字符串进行解析,然后才轮到regex来处理)。

函数如下:(str是网页源代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void find(String str) 
{
String regex = "https?://\\w+(?:\\.\\w+)+(?::\\d+)?/(?:\\w+/)*\\w+\\.(?:png|jpg|gif)";
//String regex="https?://\\w+(\\.\\w+)+(?::\\d+)?/(?:\\w+/)*\\w+\\.(?:png|jpg|gif)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
while (m.find())
{
String matchedText = m.group();
int from = m.start();
int to = m.end();
System.out.println("matched [" + matchedText + " ] from " + from + " to " + to);
}       
}

转义标签

依旧先是构建正则表达式,不多说了,直接写吧:<(\\s*[^<>]+\\s*)>,关于更多的字符一会贴在下面。

函数代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void replace(String str) 
{
String regex = "<(\\s*[^<>]+\\s*)>"
//String regex="https?://\\w+(\\.\\w+)+(?::\\d+)?/(?:\\w+/)*\\w+\\.(?:png|jpg|gif)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
StringBuffer sb =new StringBuffer();
while (m.find())
{
if(m.group(1)!=null)
{
//先将前面的字符串加上,然后加上此次的字符串
m.appendReplacement(sb, "&lt$1&gt");
}
}
//这个表示将剩下的字符加到尾部
m.appendTail(sb);
System.out.println(sb);
}

Regex的其他使用。

其实我们平时用的 String里的spilt() 和 replaceAll()都是利用到了正则表达式,这是正则表达式的简单使用。还有如果要判断一个字符串时是否是指定的格式,可以直接使用matchs() 函数。

更多详情见Java官方文档