1:多行匹配
在默认的情况下 . 是不能匹配行结束符的(行结束符有 6 个,具体的可以看看 Pattern 的 API DOC)
同样,可以像不匹配大小写匹配那样使用编译参数:Pattern.DOTALL
如果还得区分大小写的话,还得加上上面说到的 Pattern.CASE_INSENSITIVE 这个,举个例子:
Java codeimport java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
String str =
“
“
\n” +
“
\n” +
“ Hello World! \n” +
“
\n” +
“
\n” +
“
”;
String regex = “
(.+?)”;
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 还得不区分大小写的话,再改成:
Java codePattern pattern = Pattern.compile(regex, Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
这样的话,td 哪怕是大写的这个表达式都能把 td 之间的字符区抽取出来。
当然和 Pattern.CASE_INSENSITIVE 一样,Pattern.DOTALL 也有内嵌标志表达式,即 (?s)
s 的意思表示 single-line 就是忽略换行符什么的,只看成单行进行处理。
这个表达式使用内嵌 (?s) 的话可以改为:
Java codeString regex = “(?s)
(.+?)”;
如果还要不区分大小写的话,再加上 i 标志:
String regex = “(?s)(?i)
(.+?)”;
但这样显得很拖沓,可以把它们合并起来:
String regex = “(?is)
(.+?)”; // 秩序无所谓
最后需要说明一下的是,我曾看到过由于不明白 DOTALL,为了让 . 匹配行结束符,直接把表达式写成:
Java codeString regex = “
((.|\\s)+?)”;
这样做是极其危险的,由于选择结构的匹配效率问题,这样做在比较长的字符串时会造成堆栈溢出,
使程序崩溃,如果使用 DOTALL 或者 (?s) 的话就不会出现这种情况。
4:2个单元的或操作
| 称为多选结构,用于匹配 | 之中的任何一个,拿你的例子来说明:
Java codeimport java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
String str =
“
\n” + “
\n” + “
”;
String regex = “”;
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
注意到其中的 (?:ww|3) 在进行多选匹配时尽量找出多选中的规律,以减少多选的字符,
www 和 3w 在最后一个字符可以共用,前面的不一样。
(?: ) 的意思表示组成一组,如果没有 (?: ) 这样的话,表达式就变成了:
Java codeString regex = “”;
这样的语义完全变掉了,| 是在一组中进行选择,由于上面的那个表达式中没有组,就把整个表
达式作为了一组,使用 | 的话,就进行了整个表达式的多选结构了。这个表达式的意思是:
匹配 ,这样的结果并不是我们所要的。
我们仅仅需要在 ww 和 3 之间进行选择,这时只要把 ww 和 3 放在一组中进行多选择就可以了,
变成 (?:ww|3)。
还有,在多选结构中尽量把出现频率高的放在前面,这样可以加快匹配速度。
多选结构的效率在传统型的引擎中是效率低下的,如果是单个字符的选择,比如 a $ & 之中的一个,
那就不要使用 (?:a|$|&) 了,可以直接使用字符类 [a$&] 就可以了。