以下出自图灵丛书精通正则表达式一书,实验遇到的问题及解决方法,记载在此
Java正则的使用姿势
Regular Expressions API
- Pattern 描述了一种字符串模式。
- Matcher 测试一个字符串,查看它是否与该模式匹配。
正则表达式结构 | 符合匹配条件的内容 |
---|---|
. | 任何字符 |
? | 前面的0或1个字符或数字 |
* | 前面的零 (0) 或更多个字符或数字 |
+ | 前面的一 (1) 或更多个字符或数字 |
[ ] | 一个字符或数字范围 |
^ | 后面的条件的否定条件(即 “非后面的条件”) |
/d | 任何数字(也可表示为 [0-9]) |
/D | 任何非数字(也可表示为 [^0-9]) |
/s | 任何空格字符(也可表示为 [\n\t\f\r]) |
/S | 任何非空格字符(也可表示为 [^\n\t\f\r]) |
\w | 任何单词字符(也可表示为 [a-zA-Z_0-9]) |
\W | 任何非单词字符(也可表示为 [^\w]) |
\b | 查找位于单词的开头或结尾的匹配 |
$ | 检查行尾是否如下 |
(?:pattern) | 匹配 pattern 但不捕获该匹配的子表达式 |
Test1 : 找到一个具有以下形式的字符串:A 或 a 后跟零或多个字符,后跟 string。
//4nd way
Pattern pattern = Pattern.compile("[Aa].*string");//匹配string字符串之前的0或者更多字符和数字
Matcher matcher = pattern.matcher("A string");
boolean didMatch = matcher.matches();
System.out.println(didMatch);
int patternStartIndex = matcher.start();
System.out.println(patternStartIndex);
int patternEndIndex = matcher.end();
System.out.println(patternEndIndex);
- 匹配方法
每个 Java 语言字符串都是一个带索引的字符集合,索引从 0 开始,到字符串长度减 1 结束。Matcher 从 0 开始解析该字符串,寻找与它匹配的结果。完成处理后,Matcher 包含有关在输入字符串中找到(或未找到)匹配结果的信息。如果字符串中包含的元素比您搜索的模式中字符数要多,可以使用 lookingAt() 代替 matches()。
Test2 : 搜索匹配的较长的字符串信息
matches()
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by 26645 on 2017/8/31.
*/
public class RegexTest {
public static void main(String[] args) {
Pattern p = Pattern.compile(".s");//表示单个字符
Matcher m= p.matcher("as");
boolean b =m.matches();
//2nd way
boolean b2 = Pattern.compile(".s").matcher("as").matches();
//3nd way
boolean b3 = Pattern.matches(".s","as");
//4nd way
Pattern pattern = Pattern.compile("[Aa].*string");//匹配string字符串之前的0或者更多字符和数字
Scanner scan = new Scanner(System.in);
if (scan.hasNextLine()){
Matcher matcher = pattern.matcher(scan.nextLine());
boolean didMatch = matcher.matches();
System.out.println(didMatch);
int patternStartIndex = matcher.start();
System.out.println(patternStartIndex);
int patternEndIndex = matcher.end();
System.out.println(patternEndIndex);
}
}
}
console output : 字符串中包含比模式中更多的内容,查找失败
false
Exception in thread "main" java.lang.IllegalStateException: No match available
at java.util.regex.Matcher.start(Matcher.java:343)
at RegexTest.main(RegexTest.java:28)
lookingAt()
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by 26645 on 2017/8/31.
*/
public class RegexTest {
public static void main(String[] args) {
Pattern p = Pattern.compile(".s");//表示单个字符
Matcher m= p.matcher("as");
boolean b =m.matches();
//2nd way
boolean b2 = Pattern.compile(".s").matcher("as").matches();
//3nd way
boolean b3 = Pattern.matches(".s","as");
//4nd way
Pattern pattern = Pattern.compile("[Aa].*string");//匹配string字符串之前的0或者更多字符和数字
Scanner scan = new Scanner(System.in);
if (scan.hasNextLine()){
Matcher matcher = pattern.matcher(scan.nextLine());
boolean didLookingAt = matcher.lookingAt();
//boolean didMatch = matcher.matches();
System.out.println(didLookingAt);
int patternStartIndex = matcher.start();
System.out.println(patternStartIndex);
int patternEndIndex = matcher.end();
System.out.println(patternEndIndex);
}
}
}
console output:匹配失败,lookingAt()
方法只匹配正则表达式与文本的开头。
false
Exception in thread "main" java.lang.IllegalStateException: No match available
at java.util.regex.Matcher.start(Matcher.java:343)
at RegexTest.main(RegexTest.java:28)
那么如果我们想要在模式匹配中找到非0索引开头的字符串,我们应该怎么做呢?
Bingo!find()
方法,stackoverflow提议传送门
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by 26645 on 2017/8/31.
*/
public class RegexTest {
public static void main(String[] args) {
Pattern p = Pattern.compile(".s");//表示单个字符
Matcher m= p.matcher("as");
boolean b =m.matches();
//2nd way
boolean b2 = Pattern.compile(".s").matcher("as").matches();
//3nd way
boolean b3 = Pattern.matches(".s","as");
//4nd way
Pattern pattern = Pattern.compile("[Aa].*string");//匹配string字符串之前的0或者更多字符和数字
Scanner scan = new Scanner(System.in);
String str1="7-11";
String regex = "-";
Pattern ptest = Pattern.compile(regex);
Matcher m1 = ptest.matcher(str1);
System.out.println(m1.lookingAt());
if (scan.hasNextLine()){
Matcher matcher = pattern.matcher(scan.nextLine());
//boolean didLookingAt = matcher.lookingAt();
//boolean didMatch = matcher.matches();
boolean didfind = matcher.find();
System.out.println(didfind);
int patternStartIndex = matcher.start();
System.out.println(patternStartIndex);
int patternEndIndex = matcher.end();
System.out.println(patternEndIndex);
}
}
}
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=61963:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
false
Here is a vbery string
true
8
22
Process finished with exit code 0
- 正则表达式中的复杂模式
Tips:Wiki 几乎完全基于正则表达式。Wiki 内容基于来自用户的字符串输入,该输入被使用正则表达式解析和格式化。任何用户都可以通过输入一个 wiki 词组在 wiki 中创建另一个主题的链接,这个词组通常是一系列串联的单词,每个单词以一个大写字母开头
匹配目标:HereAllowed is a WikiWord followed by AnotherWikiWord,then SomeWikiWord.
String input = "HereAllowed is a WikiWord followed by AnotherWikiWord,then SomeWikiWord.";
Pattern pattern1 = Pattern.compile("[A-Z][a-z]*([A-Z][a-z]*)*");
Matcher matcher = pattern1.matcher(input);
while(matcher.find()){
System.out.println(matcher.group());
}
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=62138:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
HereAllowed
WikiWord
AnotherWikiWord
SomeWikiWord
- 匹配和操作分组
那么回归上一节,正则表达式复杂模式下匹配大写字母开头的字符串类型,并用小括号进行分隔匹配,但我们只能用这种方法么? 在对字符串操作分组更多时,
matcher.group(0)
,matcher.group(1)
的效率显然不理想,所以我们引入"分组"的概念,将匹配得到的字符串作为模板,通过在替换字符串中包含 $0 来引用完整匹配结果,即matcher.group(0)
.当我们需要制定分组时,只需要指定模板变量$之后的数字下标即可
//6th way
String input = "Here is a WikiWord followed by AnotherWikiWord,then SomeWikiWord";
Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-z][a-z]*)*");
Matcher mathcer = pattern.matcher(input);
System.out.println("Before: "+input);
String result = mathcer.replaceAll("blah$0blah");
System.out.println("After:"+result);
String result_update = mathcer.replaceAll("blah$1blah");
System.out.println("After_update: "+result_update);
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=52384:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
Before: Here is a WikiWord followed by AnotherWikiWord,then SomeWikiWord
After:blahHereblah is a blahWikiWordblah followed by blahAnotherWikiWordblah,then blahSomeWikiWordblah
After_update: blahblah is a blahWordblah followed by blahWordblah,then blahWordblah
Process finished with exit code 0
- 替换字符串
//6th way
String input = "Here is a WikiWord followed by AnotherWikiWord,then SomeWikiWord";
Pattern pattern = Pattern.compile("[A-Z][a-z]*([A-z][a-z]*)*");
Matcher mathcer = pattern.matcher(input);
System.out.println("Before: "+input);
String result = mathcer.replaceAll("blah$0blah");
System.out.println("After:"+result);
String result_update = mathcer.replaceAll("blah$1blah");
System.out.println("After_update: "+result_update);
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=52384:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
Before: Here is a WikiWord followed by AnotherWikiWord,then SomeWikiWord
After:blahHereblah is a blahWikiWordblah followed by blahAnotherWikiWordblah,then blahSomeWikiWordblah
After_update: blahblah is a blahWordblah followed by blahWordblah,then blahWordblah
- Re构造:标识符
\b
为零宽度的字符,一侧是构成单词的字符,另一侧为非单词字符、字符串的开始或结束位置。
在Java中\w
等同于[a-zA-Z0-9_]
我们以几个合法标识符举例abc,_test,$test
当匹配到一个字符串时,必定不能以数字型前缀开头,例 :123abc
。
构造思路:字符组建立
1.用\b
用来分割字符串左侧为构成单词的字符,排除数字型前缀字符串。右侧为非单词字符,排除空格
2.使用[a-zA-Z_]字符组限制右侧出现的字符类型
3.使用\w*
字符组匹配自此之前的字符串
//7th way
String line = "imooc";
String Regex_second ="\\b[a-zA-Z_]\\w*";
Pattern pattern2 = Pattern.compile(Regex_second);
Matcher matcher2 = pattern2.matcher(line);
if(matcher2.find()){
System.out.println(matcher2.group());
}
}
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=49789:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
imooc
- Re构造:提取引号内的字符串
构造思路:
1、以引号开始,任意字符,以引号结束。
2、末尾引号左边不能是\
3、末尾引号左边可以是\\
4、末尾引号左边不能是a\
//8th way
String line_second ="the\"laozi\"first";
String Regex = "\"(.*?)(?<![^\\\\]\\\\)\"";
Pattern pattern3 = Pattern.compile(Regex);
Matcher matcher = pattern3.matcher(line_second);
if(matcher.find()){
System.out.println(matcher.group());
}
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=64178:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
"laozi"
- Re构造:匹配美元金额(可能包含小数)
构造思路1:将
$
与.
转义分别用+
截断分别匹配数字型字符
构造思路2:专用
d+
代替[0-9]匹配组
//9th way
String dollar="$1000 fdgdfgdfgfdg";
String Regex = "\\$[0-9]+(\\.[0-9][0-9])?";
String Regex_first = "\\$\\d+(?:\\.\\d+)?";
Pattern pattern = Pattern.compile(Regex_first);
Matcher matcher = pattern.matcher(dollar);
if(matcher.find()){
System.out.println(matcher.group());
}
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=55131:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
$1000
- Re构造:HTML标签
div
标签(不含属性)正则式 : (?<=<div>).*(?=</div>)
div
标签(含属性)正则式 : <div[^>]*>[^<>]*
Tips : 零宽断言
用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b ^ $ \< \>
这样的锚定作用,仅仅用于指定一个位置,不参与内容匹配,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。 断言用来声明一个应该为真的事实。正则表达式中只有当断言为真时才会继续进行匹配
(?<=<div>).*(?=</div>)
正则解析
-
(?<=<div>)
先从要匹配的字符串中的最左端找到第一个<div>
,然后再匹配其后面的表达式,若无法匹配则继续查找第二个<div>
再匹配第二个<div>
后面的字符串,若能匹配则匹配。 -
(?=</div>)
从要匹配的字符串中的最右端找到第一个 </div> (然后 再匹配其前面的表达式,若无法匹配则继续查找第二个 </div> 再匹配第二个 </div> 前面的字符串,若能匹配则匹配 -
.*
在确定搜索范围之后,匹配范围内的任意字符
Tips : 贪婪模式
只要符合要求就一直匹配下去,直到无法匹配为止,即上面的结果就是2和3都存在,就往大的取!只取上限,包括、+、?都是一样的,例如ab.zz匹配abcxxzzsfewzzq的结果是abcxxzzsfewzz,并没有在abcxxzz处停止,而是直到最后的zzq不能再匹配时才停止匹配!
TestGreedyRegex.java
//13th way
String test="a<tr>aava</tr>abb ";
String reg="<.+>";
System.out.println(test.replaceAll(reg,"###"));
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=61058:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
a###abb
<div[^>]*>[^<>]*</div[^>]*>
正则解析
-
[^>]*
优先匹配排除>
的部分,回归上文,贪婪模式是一种最大匹配,在找到符合条件的字符会继续搜索下去,但当搜索到最后时,发现不能成功匹配>
,于是按照原路回退,<div>
标签至此搜索完成。 -
[^<>]*
由于我们的目标是匹配<div>
标签部分,所以在确定<>
内无多余的尖括号,以及排除掉结束标签之后,*
继续往下搜索,遇到结束标签则重复步骤1
过滤div
标签
String _input="<div>hhhhhhh</div>";
String Regex ="<div[^>]*>[^<>]* ";
String Regex_test="(?<=<div>).*(?=</div>)";
Pattern pattern = Pattern.compile(Regex);
Matcher matcher = pattern.matcher(etreeHtml);
if(matcher.find()){
System.out.println(matcher.group());
}
img
标签src正则式 : src\\s*=\\s*\"?(.*?)(\"|>|\\s+)
img
标签(包括括号) : <img.*src\\s*=\\s*(.*?)[^>]*?>
过滤img
标签
String _input ="<img src=image/ad1.gif width=\"128\" height=\"36\"/>![](image/ad2.gif)";
String Regex ="src\\s*=\\s*\"?(.*?)(\"|>|\\s+)";
Pattern pattern = Pattern.compile(Regex);
Matcher matcher = pattern.matcher(_input);
boolean notice = matcher.find();
System.out.println(notice);
if(matcher.find()){
System.out.println(matcher.group());
}
style
标签正则式:<[\s]*?style[^>]*?>[\s\S]*?<[\s]*?\/[\s]*?style[\s]*?>
Tips : 勉强模式:
如果说贪婪模式是最大匹配,那么勉强模式就是一种最小匹配。 Java是支持勉强模式的,勉强模式的表示方式是重复次数字符后面紧跟一个?
,例如??
就表示勉强模式的?
,+?
就表示勉强模式的+
,*?
就表示勉强模式的*
,{ }?
就表示勉强模式的{ }
;其意义为一找到符合要求的就立马匹配成功,不再管后面的序列,在勉强模式下*匹配0个,+匹配一个,?匹配0个,而{ }只匹配下限
TestReluctantlyRegex
//13th way
String test="a<tr>aava</tr>abb ";
String reg="<.+?>";
System.out.println(test.replaceAll(reg,"###"));
console output
D:\java\jdk1.8.0_51\bin\java "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=65466:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk1.8.0_51\jre\lib\charsets.jar;D:\java\jdk1.8.0_51\jre\lib\deploy.jar;D:\java\jdk1.8.0_51\jre\lib\ext\access-bridge-64.jar;D:\java\jdk1.8.0_51\jre\lib\ext\cldrdata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\dnsns.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jaccess.jar;D:\java\jdk1.8.0_51\jre\lib\ext\jfxrt.jar;D:\java\jdk1.8.0_51\jre\lib\ext\localedata.jar;D:\java\jdk1.8.0_51\jre\lib\ext\nashorn.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunec.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunjce_provider.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunmscapi.jar;D:\java\jdk1.8.0_51\jre\lib\ext\sunpkcs11.jar;D:\java\jdk1.8.0_51\jre\lib\ext\zipfs.jar;D:\java\jdk1.8.0_51\jre\lib\javaws.jar;D:\java\jdk1.8.0_51\jre\lib\jce.jar;D:\java\jdk1.8.0_51\jre\lib\jfr.jar;D:\java\jdk1.8.0_51\jre\lib\jfxswt.jar;D:\java\jdk1.8.0_51\jre\lib\jsse.jar;D:\java\jdk1.8.0_51\jre\lib\management-agent.jar;D:\java\jdk1.8.0_51\jre\lib\plugin.jar;D:\java\jdk1.8.0_51\jre\lib\resources.jar;D:\java\jdk1.8.0_51\jre\lib\rt.jar;E:\kotlin_learn\out\production\kotlin_learn;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-runtime.jar;C:\Users\26645\.IntelliJIdea2017.1\config\plugins\Kotlin\kotlinc\lib\kotlin-reflect.jar;E:\kotlin_learn\junit-4.12.jar RegexTest
a###aava###abb
<[\s]*?style[^>]*?>[\s\S]*?<[\s]*?\/[\s]*?style[\s]*?>
正则解析 :
-
[\s]*?
为了排除设计者在开发过程中出现不慎输入空格的情况,在匹配一个空格字符后,继续匹配style
标签。 - 如果失败,再匹配一个空格字符,看是否有匹配
style
的可能,如是,继续向下搜索,匹配成功一个字符后,继续匹配>
,重复步骤1 -
[\s\S]*?
在我们输入style
标签关联样式表之后,通常会换行添加属性,在遇到下一个<
之前,这些换行字符是不可忽略的,如果忽略。对于换行的style
标签内则匹配失败 -
[\s]*?
排除结束标签多余的空格,\/
为java字符转义,在此无意义
过滤style
标签:
// //10th
StringBuilder etreeHtml =new StringBuilder("<html>\n" +
"<head>\n" +
" <meta charset=\"utf-8\" />\n" +
" <title>HTML Editor</title>\n" +
" <style type=\"text/css\">\n" +
" .main { float: left;\n" +
" width: 100%; }\n" +
" \n" +
" #editor { float: left;\n" +
" width: 49%;\n" +
" height: 600px;\n" +
" resize: none; }\n" +
" \n" +
" #page { float: right;\n" +
" width: 49%;\n" +
" height: 600px;}\n" +
" </style>\n" +
"</head>\n" +
" \n" +
"<body>\n" +
" <div class=\"main\">\n" +
" <p style=\"float:left; width:49%; color:red;\">This is your code.</p>\n" +
" <p style=\"float:right; width:49%; color:red;\">This is your page.</p>\n" +
" </div>\n" +
" \n" +
" <div class=\"main\">\n" +
" <textarea id=\"editor\" onkeyup=\"showPage()\"></textarea>\n" +
" <div id=\"page\"></div>\n" +
" </div>\n" +
" <div>\n"+
" gfgfgfgfg\n"+
" </div>"+
" \n" +
" <script type=\"text/javascript\">\n" +
" function showPage(){\n" +
" code = document.getElementById('editor').value;\n" +
" page = document.getElementById('page');\n" +
" page.innerHTML = code;\n" +
" }\n" +
" </script>\n" +
" \n" +
"</body>\n" +
"</html>");
String Regex = "(?id)<style\\s+(.*?)/?>";//匹配独立的img tags
String Width_Regex = "(?ix)\\bwidth:(\\S+)";
//定义style的正则表达式{或<style[^>]*?>[\\s\\S]*?<\\/style>
String regEx_style = "<[\\s]*?style[^>]*?>[\\s\\S]*?<[\\s]*?\\/[\\s]*?style[\\s]*?>";
// Matcher mStyle = Pattern.compile(Regex).matcher(etreeHtml);
// Matcher mWidth =Pattern.compile(Width_Regex).matcher(etreeHtml);
Pattern pattern = Pattern.compile(regEx_style);
Matcher mStyle = pattern.matcher(etreeHtml);
if(mStyle.find()){
System.out.println(mStyle.group());
}