文章出处:http://topic.csdn.net/u/20080627/14/8a91b33a-f35c-4303-85b5-e0a8da462202.html
1 多行匹配
2 不以某某开头 ,比如不以www开头
3 不区分大小写
4 2个单元的或操作,比如 www ¦ 3w 都可以这种
火龙果回答:
1:多行匹配
在默认的情况下 . 是不能匹配行结束符的(行结束符有 6 个,具体的可以看看 Pattern 的 API DOC)
同样,可以像不匹配大小写匹配那样使用编译参数:Pattern.DOTALL
如果还得区分大小写的话,还得加上上面说到的 Pattern.CASE_INSENSITIVE 这个,举个例子:
- import java.util.regex.Matcher;
-
import java.util.regex.Pattern;public class Test {
-
-
public static void main(String[] args) {
- String str =
-
"<table> \n" +
-
" <tr> \n" +
-
" <td> \n" +
-
" Hello World! \n" +
-
" </td> \n" +
-
" </tr> \n" +
-
"</table>";
-
String regex = "<td>(.+?)</td>";
- Pattern pattern = Pattern.compile(regex);
- Matcher matcher = pattern.matcher(str);
-
while(matcher.find()) {
-
System.out.println(matcher.group(1).trim());
- }
- }
- }
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Test {
public static void main(String[] args) {
String str =
"<table> \n" +
" <tr> \n" +
" <td> \n" +
" Hello World! \n" +
" </td> \n" +
" </tr> \n" +
"</table>";
String regex = "<td>(.+?)</td>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()) {
System.out.println(matcher.group(1).trim());
}
}
}
上面这个是不能从 str 抽取出东西的,因为 td 的后面带有换行符,我们只要更改一下:
Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
这样就行了,如果 td 还得不区分大小写的话,再改成:
Pattern pattern = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
这样的话,td 哪怕是大写的这个表达式都能把 td 之间的字符区抽取出来。
当然和 Pattern.CASE_INSENSITIVE 一样,Pattern.DOTALL 也有内嵌标志表达式,即 (?s)
s 的意思表示 single-line 就是忽略换行符什么的,只看成单行进行处理。
这个表达式使用内嵌 (?s) 的话可以改为:
String regex = "(?s)<td>(.+?)</td>";
如果还要不区分大小写的话,再加上 i 标志:
String regex = "(?s)(?i)<td>(.+?)</td>";
但这样显得很拖沓,可以把它们合并起来:
String regex = "(?is)<td>(.+?)</td>"; // 秩序无所谓
最后需要说明一下的是,我曾看到过由于不明白 DOTALL,为了让 . 匹配行结束符,直接把表达式写成:
String regex = "<td>((.|\\s)+?)</td>";
这样做是极其危险的,由于选择结构的匹配效率问题,这样做在比较长的字符串时会造成堆栈溢出,
使程序崩溃,如果使用 DOTALL 或者 (?s) 的话就不会出现这种情况。
2:不以某某开头 ,比如不以www开头
- public class Test {
-
-
public static void main(String[] args) {
- String[] strs = {
-
"abc1232", "wwwadsf",
-
"awwwfas", "wwadfsf",
-
"", "ww", " ", "www"
- };
-
String regex = "(?:(?!^www).)*";
-
for(String str : strs) {
-
System.out.printf("%-7s %s%n", str, str.matches(regex));
- }
- }
- }
public class Test {
public static void main(String[] args) {
String[] strs = {
"abc1232", "wwwadsf",
"awwwfas", "wwadfsf",
"", "ww", " ", "www"
};
String regex = "(?:(?!^www).)*";
for(String str : strs) {
System.out.printf("%-7s %s%n", str, str.matches(regex));
}
}
}
(?!X) 专业名称为 Negative Lookahead,表示字符间缝隙后面不允许出现的字符,
即匹配字符间的缝隙,如果缝隙后的字符不是 X 的话,那这个缝隙就匹配成功。
举个例子,aab 和 aac,现有表达式 aa(?!b) 这时我们能匹配到的字符串是 aac,
因为 aa 的后面的缝隙之后不允许出现字符 b,因此只有 aac 进行了匹配。
再来看个示例:
- public class Test {
-
public static void main(String[] args) {
-
String str = "AQuickBrownFoxJumpsOverTheLazyDog";
-
String[] strs = str.split("(?<!^)(?=[A-Z])");
-
for(String s : strs) {
- System.out.println(s);
- }
- }
- }
public class Test {
public static void main(String[] args) {
String str = "AQuickBrownFoxJumpsOverTheLazyDog";
String[] strs = str.split("(?<!^)(?=[A-Z])");
for(String s : strs) {
System.out.println(s);
}
}
}
根据大写字母拆分字符串。当然了,这个使用字符串进行分析同样也能进行拆分,
但是使用正则表达式来拆的话更为便捷直观一些。
在进行这种拆分时,由于在拆分后的字符数不能减少,因此只能使用零宽度的
lookaround 功能进行匹配,lookaround 包括四个,即:
(?=X) (?!X) (?<=X) (?<!X)
来看一下这个表达式:(? <!^)(?=[A-Z])
前面说到过 (?!) 表示缝隙后面不允许出现的东西,而 (? <!) 表示缝隙前不允许出现的东西。
(?=) 表示缝隙后允许出现的东西,(? <=) 表示缝隙前允许出现的东西。
这个表达式在拆分时,根据零宽度匹配缝隙进行拆分的,这个缝隙必须满足以下条件:
(? <!^) 表示缝隙不允许前不能是行开始,即缝隙不能出现在首字母的前面。
(?=[A-Z]) 表示缝隙后面允许出现 A-Z 的大写字母。
这时这个表达式就匹配了下面带有 ¦ 的缝隙:
A|Quick|Brown|Fox|Jumps|Over|The|Lazy|Dog
PS:不加 (?<!^) 的话,会变成:
|A|Quick|Brown|Fox|Jumps|Over|The|Lazy|Dog
根据 split 的功能,正则表达式处理程序就根据上面的 ¦ 将字符串给拆分开来了。
3,不区分大小写
不加任何限制的匹配是匹配分大小写的,但是正则表达式中可以进行改变,
有两种方式:参数式和内嵌式。
来看个示例:
- import java.util.regex.Matcher;
-
import java.util.regex.Pattern;public class Test {
-
-
public static void main(String[] args) {
-
String str = "Book";
-
Pattern pattern = Pattern.compile("book");
- Matcher matcher = pattern.matcher(str);
- System.out.println(matcher.matches());
- }
- }
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Test {
public static void main(String[] args) {
String str = "Book";
Pattern pattern = Pattern.compile("book");
Matcher matcher = pattern.matcher(str);
System.out.println(matcher.matches());
}
}
上面的这个表达式 book 是不能匹配字符串 Book 的,这时我们只要给定编译时的参数就可以了:
Pattern pattern = Pattern.compile("book", Pattern.CASE_INSENSITIVE);
Pattern.CASE_INSENSITIVE 这是一个 int 类型的常量,值为 2。表示表达式忽略大小写进行区配。
如果我们不采用 Pattern 和 Matcher 两个类来匹配的话,只是使用 String 的 matches 方法的话,
我们就不能指定表达式的编译参数了,这时就需要采用内嵌标志表达式了,与 Pattern.CASE_INSENSITIVE
对应的内嵌标志表达式是 (?i),它有四种形式:
1,(?i)
2,(?-i)
3,(?i:X)
4,(?-i:X)
不带有 - 的是开标志,带有 - 的是关标志。
把上面的代码改成这样:
- public class Test {
-
-
public static void main(String[] args) {
-
String str = "Book";
-
String regex = "(?i)book";
- System.out.println(str.matches(regex));
- }
- }
public class Test {
public static void main(String[] args) {
String str = "Book";
String regex = "(?i)book";
System.out.println(str.matches(regex));
}
}
我们就达到了同样的效果,当然这样并不是最好的,因为字符串中只有 B 是大写的,
我们没有必要把所有的字符都进行不区分大小写匹配,我们可以在打开标志,用 (?i) 的
第二种形式马上关掉它:
String regex = "(?i)b(?-i)ook";
这样的话,只有 b 是区分大小写了,而 (?-i) 后面的还是得区分大小写匹配的。这样写
可能看上去很不顺眼,我们还能使用第 3 种形式直接指定某些字符是不区分大小写的。
String regex = "(?i:b)ook";
这样的表达式与上面的那个在语义上是相同的。就效率上肯定是优于一下子开,一下子关的。
可见内嵌标志表达式要比指定编译参数的功能强大许多。
使用建议:如果能确定某些字符的大小写时,尽量使用已确定的字符,对于不确定的可以采用
(?i:X) 的方式指定。因此打开不区分大小写开关时,对匹配的性能是有一定影响的。
思考一下:String regex = "(?i)b(?-i:oo)k"; 这个表达式的意思?
另外:第 1 和第 4,我没看明白需要了解什么,请在下面的楼层中具体地说明一下。
4:2个单元的或操作
¦ 称为多选结构,用于匹配 ¦ 之中的任何一个,拿你的例子来说明:
- import java.util.regex.Matcher;
-
import java.util.regex.Pattern;public class Test {
-
-
public static void main(String[] args) {
- String str =
-
"<img src=\"http://www.google.com/1.gif\"/>\n" +
-
"<img src=\"http://3w.google.com/1.gif\"/>\n" +
-
"<img src=\"http://abc.baidu.com/1.gif\"/>";
-
String regex = "<img\\ssrc=\"http://(?:ww|3)w.google.com/1.gif\"/>";
- Pattern pattern = Pattern.compile(regex);
- Matcher matcher = pattern.matcher(str);
-
while(matcher.find()) {
- System.out.println(matcher.group());
- }
- }
- }
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class Test {
public static void main(String[] args) {
String str =
"<img src=\"http://www.google.com/1.gif\"/>\n" +
"<img src=\"http://3w.google.com/1.gif\"/>\n" +
"<img src=\"http://abc.baidu.com/1.gif\"/>";
String regex = "<img\\ssrc=\"http://(?:ww|3)w.google.com/1.gif\"/>";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
注意到其中的 (?:ww ¦3) 在进行多选匹配时尽量找出多选中的规律,以减少多选的字符,
www 和 3w 在最后一个字符可以共用,前面的不一样。
(?: ) 的意思表示组成一组,如果没有 (?: ) 这样的话,表达式就变成了:
String regex = "<img\\ssrc=\"http://ww|3w.google.com/1.gif\"/>";
这样的语义完全变掉了, ¦ 是在一组中进行选择,由于上面的那个表达式中没有组,就把整个表
达式作为了一组,使用 ¦ 的话,就进行了整个表达式的多选结构了。这个表达式的意思是:
匹配 <img ssrc="http://ww 或者是 3w.google.com/1.gif"/>,这样的结果并不是我们所要的。
我们仅仅需要在 ww 和 3 之间进行选择,这时只要把 ww 和 3 放在一组中进行多选择就可以了,
变成 (?:ww ¦3)。
还有,在多选结构中尽量把出现频率高的放在前面,这样可以加快匹配速度。
多选结构的效率在传统型的引擎中是效率低下的,如果是单个字符的选择,比如 a $ & 之中的一个,
那就不要使用 (?:a ¦$ ¦&) 了,可以直接使用字符类 [a$&] 就可以了。
5:split分割字母和数字,简单正则缝隙
- public class Test01 {
-
public static void main(String[] args) {
-
String str = "one123";
-
String regex = "(?<=one)(?=123)";
- String[] strs = str.split(regex);
-
for(int i = 0; i < strs.length; i++) {
-
System.out.printf("strs[%d] = %s%n", i, strs[i]);
- }
- }
- }
public class Test01 {
public static void main(String[] args) {
String str = "one123";
String regex = "(?<=one)(?=123)";
String[] strs = str.split(regex);
for(int i = 0; i < strs.length; i++) {
System.out.printf("strs[%d] = %s%n", i, strs[i]);
}
}
}
分享到:
相关推荐
本文档结合多年使用正则表达式经验,总结正则表达式使用方式以及常见的正则表达式的表达。希望有助于您的学习!
自己在工作中对正则表达式,apache重写规则等常用到的总结。
正则表达式经验谈 总结正则表达式常用的方法及出现的问题
方法1:依据经验构建正则表达式... 262 真正的“消除循环”解法... 264 方法2:自顶向下的视角... 266 方法3:匹配主机名... 267 观察... 268 使用固化分组和占有优先量词... 268 简单的消除循环的例子... ...
正则表达式学习的最好的教程,纯个人经验总结,适合初学者
第 1 章 正则表达式入门 29 解决实际问题 30 作为编程语言的正则表达式 32 以文件名做类比 32 以语言做类比 33 正则表达式的思维框架 34 对于有部分经验的读者 34 Egrep元字符 36 行的起始和结束 36 字符组...
总结了点正则表达式的经验《===================共享共享
常用的正则表达式绝对好用,本人用过的经验总结!
学python的re模板,写了个文章发现没人看,所以总结出来经验,理论没人爱,实战的人心,那么既然没人喜欢理论就直接上实战,在实战中精炼理论.不多说直接先上代码 def password_level(password): weak = re....
总结在 python 语言里使用正则表达式匹配中文的经验。
自己根据这些年的经验,把能够用到的做了一个总结
所以满脑子都是考虑的优化两个字,不过还好之前是搞算法竞赛的,效率这个问题也一直是做斗争的对象,还算习惯吧,最近写正则也比较多,所以参考参考书、博文、自己的经验写点总结性的优化策略
3.2 各记号对应的正则表达式及所有记号对应的正则表达式; 3.3 各记号对应的DFA及所有记号对应的DFA; 4 扫描程序的功能说明和程序说明,程序模块等; 5 输入示例及其运行结果; 6 总结: 获得的经验,遇到的...
3.2 各记号对应的正则表达式及所有记号对应的正则表达式; 3.3 各记号对应的DFA及所有记号对应的DFA; 4 扫描程序的功能说明和程序说明,程序模块等; 5 输入示例及其运行结果; 6 总结: 获得的经验,遇到的问题,改进方案...
关于正则表达式的使用,更多的是自己的经验,有兴趣可以参阅相关书籍。这里主要写一下java中的正则操作方法
本人多年实践经验总结的,包括输入域正则表达式,长度,字符串处理等。需要的自己看吧!
1. 表格标签是table,tr是行,td是单元格,cellspacing是单元格与单元格的距离 cellpadding是内边距,...6.正则表达式是一种专门用于操作字符串的规则 通过一些符号来表示,简化对字符串操作 常见的操作有 匹配:matc
可以使用正则表达式对做字符串替换,将短横替换为斜杠。 var iosDate= date.replace(/-/g, '/'); 。 2. wx.getUserInfo()接口更改问题 微信小程序最近被吐槽最多的一个更改,就是用户使用wx.getUser
经验总结 PHP开发者实践 规范写作 PHP The Right Way PHP Best Practices PHP-FIG PSR中文版 PHP Package Checklist Keep a CHANGELOG Best Practices for Modern PHP Development 文章 Sort常见排序算法 Chrome...