加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

令人抓狂的代码 - 万能正则表达式.*陷阱

发布时间:2020-12-14 06:42:06 所属栏目:百科 来源:网络整理
导读:转载请注明joymufeng,欢迎访问 PlayScala社区(http://www.playscala.cn) 原文链接:http://www.playscala.cn/article/view?_id=10-59ee9f831d00000f0033a556 先尝试执行下面的代码: println("play n scala".matches(".*")) 你没看错,打印结果是false。正
转载请注明joymufeng,欢迎访问 PlayScala社区(http://www.playscala.cn)

原文链接:http://www.playscala.cn/article/view?_id=10-59ee9f831d00000f0033a556

先尝试执行下面的代码:

println("play n scala".matches(".*"))

你没看错,打印结果是false。正如键盘布局一样,这是由于一个历史问题导致的。早期的正则表达式工具是基于行处理文本的,所以.匹配的是除换行符以外的任意字符。大多数编程语言在设计正则表达式时沿用了这个传统,但是提供一个选项用于开启"点号匹配换行符"模式。

Java提供了两种方式开启"点号匹配换行符"模式,第一种方式是在构建Pattern对象时指定匹配模式:

val p = Pattern.compile(".*",Pattern.DOTALL)
println(p.matcher("playnscala").matches()) // true

另一种方式是在正则表达式开始位置指定嵌入模式修饰符(embedded mode modifier),这也是一种比较通用的方式:

println("playnscala".matches("(?s).*")) // true

Pattern.DOTALL和(?s)是等价的。

Java常用的匹配模式有以下几种:

1) Pattern.DOTALL

启用dotall模式。在dotall模式下,模式中的.匹配任意字符,包括换行符。在默认情况下(即未启用dotall模式),.不匹配换行符。等价于修饰符(?s)。

val p = Pattern.compile(".*",Pattern.DOTALL)
val m = p.matcher("playnscala")
println(m.matches())
// 输出
true

2)Pattern.MULTILINE

启用多行匹配模式。在多行匹配模式下,模式中的^和$将逐次匹配每一行的行首和行尾。在默认情况下(即未启用多行匹配模式),^和$将匹配整个字符串的首部和尾部。等价于修饰符(?m)。

val p = Pattern.compile("^.*$",Pattern.MULTILINE)
val m = p.matcher("playnscala")
while (m.find()) {
  println("find: " + m.group(0))
}

// 输出
find: play
find: scala

3) Pattern.UNIX_LINES

启用Unix换行模式,使用"n"标识每一行的末尾,等价于修饰符(?d)。

val p = Pattern.compile("^.*$",Pattern.UNIX_LINES | Pattern.MULTILINE)
val m = p.matcher("playrnscala")
while (m.find()) {
  println("find: " + m.group(0).length)
}
// 输出
find: 5
find: 5

输出的两个结果长度都为5,原因是play末尾还有一个字符r。

4)Pattern.CASE_INSENSITIVE

启用大小写不敏感匹配,等价于修饰符(?i)。

val p = Pattern.compile("^S.*A$",Pattern.CASE_INSENSITIVE)
val m = p.matcher("scala")
println(m.matches())
// 输出
true

5)Pattern.LITERAL

启用字面(literal)模式解析,模式中的元字符和转义字符将按照普通字符解析。

val p = Pattern.compile(".*",Pattern.LITERAL)
val m = p.matcher("scala")
println(m.matches())
// 输出
false

6)Pattern.COMMENTS

正则表达式中允许出现空白符(whitespace)和注解(comments),空白符会被忽略,以#开头的注解行也将被忽略,等价于修饰符(?x);

val p = Pattern.compile(" .* ",Pattern.COMMENTS)
val m = p.matcher("scala")
println(m.matches())
// 输出
true

注:有些编程语言(例如JavaScript)不支持嵌入模式修饰符(embedded mode modifier),这时可以使用另一种解决方案:

[sS]*

[s]会匹配任意空白字符,[S]而则会匹配[s]不能匹配的任意字符。把这二者组合起来构成[sS],这样就会得到一个包含所有字符的字符组,其中也包含了换行符。

参考:

正则表达式经典实例(第2版)

Java Pattern Doc

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读