Java 中的正则表达式
1. Java 的正则流派
- java.util.regex 使用传统型 NFA
- 匹配模式的启用通过各种 method 和 factory 来设定标志位, 或内嵌在表达式中的
(?mods-mods)
和 (?mode-mods:...)
修饰符
![这里写图片描述](https://img-blog.csdn.net/20170118155115032?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbHN6YmQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
字符缩略表示法
元字符 | 说明 |
---|
\a | |
[\b] | 只有在字符组内, \b 才表达退格字符, 其他场合都是表达单词分界符 |
\e | |
\f | |
\n | |
\r | |
\t | |
\0octal | 要求开头为 0, 后接 1 到 3 位十进制数字 |
\x## | 只容许出现两位十六进制数字, 例如 \x7Aber 匹配 zber |
\u#### | 只容许出现四位十六进制数字, 例如 \x007Aber 匹配 zber |
\cchar | 区分大小写, 直接对后面字符的十进制编码进行异或操作 |
字符组及相关结构
元字符 | 说明 |
---|
[…][^…] | 字符组, 可包含集合运算符 |
. | 点号, 几乎任何字符, 根据模式不同, 有各种含义 |
\p{Prop} \P{Prop} | Unicode 属性和区块 |
\w | [0-9a-zA-Z] |
\W | [^0-9a-zA-Z] |
\d | [0-9] |
\D | [^0-9] |
\s | [.\t\n\f\r\0x0b] |
\S | [^.\t\n\f\r\0x0b] |
锚点及其他零长度断言
元字符 | 说明 |
---|
^ \A | 行/字符串起始位置 |
$ \z \Z | 行/字符串结束位置 |
\G | 当前匹配的起始位置 |
\b \B | 单词分界符, 可以识别 Unicode 字符 |
(?=…) (?!…) (?<=…) (? | 环视结构, 逆序环视中的子表达式只能匹配长度有限的文本 |
注释及模式修饰符
元字符 | 说明 |
---|
(?mods-mods) | 模式修饰符, 容许出现的模式: x d s m i u |
(?mods-mods:…) | 模式修饰范围 |
# | 注释, 从 # 到行未(只在启用时有效, \x 修饰符或 Pattern.COMMENTS ) |
\Q…\E | 文字文本模式 |
分组及捕获
元字符 | 说明 |
---|
(…) \1 \2… | 捕获型括号 |
(?:…) | 仅分组的括号 |
(?>…) | 固化分组 |
** | ** |
* + ? {n} {n,} {n,m} | 匹配优先量词 |
*? +? ?? {n}? {n,}? {n,m}? | 忽略优先量词 |
*+ ++ ?? {n}+ {n,}+ {n,m}+ | 占有优先量词 |
Match 和 Regex 的方法
编译选项 | (?mode) | 描述 |
---|
Pattern.UNIX_LINES | d | 更改点号和 ^ 的匹配 |
Pattern.DOTALL | s | 点号能匹配任何字符 |
Pattern.MULTILINE | m | 扩展 ^ 和 $ 的匹配规定 |
Pattern.COMMENTS | x | 宽松排列和注释模式(在字符组内部也有效) |
Pattern.CASE_INSENSITIVE | i | 对 ASCII 字符进行不区分大小写的匹配 |
Pattern.UNICODE_CASE | u | 对 Unicode 字符进行不区分大小写的匹配 |
Pattern.CANON_EQ | | Unicode 按规则等价匹配模式(不同编码中的同样字符视为相等) |
Pattern.LITERAL | | 将 regex 参数作为文字文本, 而非正则表达式 |
2. 使用 java.util.regex
import java.util.regex.*;
public class JavaRegex {
public static void main(String[] args) {
String text = "this is my 1Test string";
String regex = "\\d+t";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
Matcher matcher = pattern.matcher(text);
if(matcher.find()) {
String matchedText = matcher.group();
int start = matcher.start();
int end = matcher.end();
System.out.println("matchedText : " + matchedText + ", index : " + start + "~" + end);
}
}
}
3. Matcher 对象
- 将正则表达式和目标字符串联系起来, 可以以多种方式将将应用到目标字符串中, 并查询应用的结果
3.1 常用方法
# 可以设置和修改元素的方法
matcher.pattern()
matcher.usePattern(pattern)
matcher.reset(text)
matcher.region(start, end)
matcher.useAnchoringBounds(b)
matcher.useTransparentBounds(b)
# 访问只读元素的方法
matcher.groupCount()
matcher.find()
matcher.hitEnd()
matcher.group(group)
matcher.toMatchResult()
3.2 应用正则表达式
public static void main(String[] args) {
String text = "Mastering Regular Expressions";
String regex = "\\w+";
Matcher matcher = Pattern.compile(regex).matcher(text);
if(matcher.find()) {
System.out.println(matcher.group());
}
while(matcher.find()) {
System.out.println(matcher.group());
}
if(matcher.find(10)) {
System.out.println(matcher.group());
}
"1234".matches("\\d+");
"123!".matches("\\d+");
}
/************************************ 查询匹配结果 ************************************/
public static void main(String[] args) {
String url = "http://regex.info/blog";
String regex = "(?x)^(https?)://([^/:]+)(?:(\\d+))?";
Matcher matcher = Pattern.compile(regex).matcher(url);
if(matcher.find()) {
System.out.println(matcher.group() + " " + matcher.start() + "~" + matcher.end());
System.out.println(matcher.group(1) + " " + matcher.start(1) + "~" + matcher.end(1));
System.out.println(matcher.group(2) + " " + matcher.start(2) + "~" + matcher.end(2));
}
if(matcher.group(3) == null) {
System.out.println("没有指定指定端口号");
}else {
System.out.println("端口号 : " + matcher.group(3));
}
}
/************************************ 简单查找和替换 ************************************/
public static void main(String[] args) {
String text = "Before Java 1.5 was Java 1.4.2 After Java 1.5";
String regex = "\\bJava\\s*1\\.5\\b*";
Matcher matcher = Pattern.compile(regex).matcher(text);
String firstResult = matcher.replaceFirst("Java 5.0");
System.out.println(firstResult);
String result = matcher.replaceAll("Java 5.0");
System.out.println(result);
}
/************************************ 高级查找-替换 ************************************/
public static void main(String[] args) {
Matcher m = Pattern.compile("cat").matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString());
}
/**
* 自己实现 replaceAll 方法
*/
public static String replaceAll(Matcher m, String replacement) {
m.reset();
StringBuffer sb = new StringBuffer();
while(m.find()) {
m.appendReplacement(sb, replacement);
}
m.appendTail(sb);
return sb.toString();
}
/************************************ 原地查找-替换 ************************************/
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("It's SO very RUDE to shout");
Matcher matcher = Pattern.compile("\\b[\\p{Lu}\\p{Lt}]+\\b").matcher(sb);
while(matcher.find())
sb.replace(matcher.start(), matcher.end(), matcher.group().toLowerCase());
System.out.println(sb.toString());
}
/************************************ 长度变化的替换 ************************************/
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("It's SO very RUDE to shout");
Matcher matcher = Pattern.compile("\\b[\\p{Lu}\\p{Lt}]+\\b").matcher(sb);
int matchPointer = 0;
while(matcher.find()) {
matchPointer = matcher.end();
sb.replace(matcher.start(), matcher.end(), "<b>" + matcher.group().toLowerCase() + "</b>");
matchPointer += 7;
}
System.out.println(sb.toString());
}
/************************************ 限定范围查找 ************************************/
public static void main(String[] args) throws IOException {
InputStream is = new URL("http://www.cnblogs.com/xing901022/p/5978989.html").openStream();
String html = new String(IOUtils.readFully(is, is.available(), true));
Matcher mImg = Pattern.compile("(?id)<IMG\\s+(.*?)/?>").matcher(html);
Matcher mAlt = Pattern.compile("(?id)\\b ALT \\S* =").matcher(html);
while(mImg.find()) {
mAlt.region(mImg.start(1), mImg.end(1));
if(!mAlt.find()) {
System.out.println(mImg.group());
}
}
}
/************************************ 边界透明 ************************************/
public static void main(String[] args) throws IOException {
String text = "Madagascar is best seen by car or bike.";
Matcher matcher = Pattern.compile("\\bcar\\b").matcher(text);
matcher.region(7, text.length());
matcher.useTransparentBounds(true);
matcher.find();
System.out.println(matcher.start());
}
4. Pattern 的其它方法
pattern.split(input);
pattern.pattern();
pattern.toString();
pattern.flags();
pattern.quote(s);
pattern.matches(regex, input)
/************************************ split 方法说明 ************************************/
Pattern.compile(":").split(":xx:");
Pattern.compile(":").split(":xx:", -1);
Pattern.compile(":").split(":xx:", 0);
Pattern.compile(":").split(":xx:", 1);
5. 拓展示例
为 Image Tag 添加宽度和高度属性
public static void main(String[] args) throws IOException {
StringBuffer html = new StringBuffer("<img src=https://www.baidu.com/img/bd_logo1.png /><img src=https://www.baidu.com/img/bd_logo1.png />");
Matcher mImg = Pattern.compile("(?id)<img\\s(.*?)/?>").matcher(html);
Matcher mSrc = Pattern.compile("(?ix)\\bSrc=(\\S+)").matcher(html);
Matcher mWidth = Pattern.compile("(?ix)\\bWidth=(\\S+)").matcher(html);
Matcher mHeight = Pattern.compile("(?ix)\\bHeight=(\\S+)").matcher(html);
int imgMatchPointer = 0;
while(mImg.find(imgMatchPointer)) {
imgMatchPointer = mImg.end();
boolean hasSrc = mSrc.region(mImg.start(1), mImg.end(1)).find();
boolean hasWidth = mWidth.region(mImg.start(1), mImg.end(1)).find();
boolean hasHeight = mHeight.region(mImg.start(1), mImg.end(1)).find();
if(hasSrc && (!hasWidth || !hasHeight)) {
BufferedImage img = ImageIO.read(new URL(mSrc.group(1)));
String size;
if(hasWidth) {
size = "height='" + ((int)(Integer.parseInt(mWidth.group(1)) * img.getHeight() / img.getWidth()) + "' ");
}else if(hasHeight) {
size = "width=" + ((int)(Integer.parseInt(mWidth.group(1)) * img.getWidth() / img.getHeight()) + "' ");
}else {
size = "width=" + img.getWidth() + "' " + "height='" + img.getHeight() + "' ";
}
html.insert(mImg.start(1), size);
imgMatchPointer += size.length();
}
}
System.out.println(html.toString());
}