检测正则表达式中特定puntucations的奇怪行为

时间:2015-10-15 21:13:56

标签: java regex encoding

以下代码:

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Main {

public static void main(String[] args) {
    // TODO Auto-generated method stub

          // Create a Pattern object
          Pattern r = Pattern.compile("[?:!.,;'’\"“”«»<>=()_-]+");

          // Now create matcher object.
          Matcher m = r.matcher("Hello,World!");

          while(m.find())
            System.out.println(m.group());

         }
}

输出:

,
!

如果我在正则表达式(更长的连字符)中添加标点符号,使其变为:

Pattern r = Pattern.compile("[?:!.,;'’\"“”«»<>=()_-–]+");

输出变为:

ello, 
orld!

有谁能告诉我为什么会出现这种奇怪的故障?

2 个答案:

答案 0 :(得分:4)

这是因为-_之间的短划线()创建了一个范围,并且包含Unicode代码点介于_和{{1之间的所有字符}}

  • 是U + 005F
  • _是U + 2013

所以介于两者之间的所有内容都包含在范围内。这包括小写拉丁字符(范围从U + 0061到U + 007A)。

大写拉丁字符的范围从U + 0041到U + 005A,因此位于之前 U + 005F的下划线。这些被排除在角色类之外。

将短划线放在角色类的开头或结尾以解决问题。

或者,您可以使用反斜杠来逃避它,但我建议您坚持使用第一个/最后一个规则,因为它更容易阅读。

答案 1 :(得分:1)

一些基础知识:

所有正则表达式特殊字符都可以在类之外转义 调用其 literal 含义。

内部课程,乍一看,ascii短划线符号-范围操作符,
你记得。

要调用其字面含义,可以将其放在
的开头或结尾 类。

但是,正则表达式解析比你想象的要简单得多 将破折号放在一个类中的位置并不重要。

从左到右解析单个字符,单个字符代表
左边的位置。如果破折号是找到的下一个字符,则下一个字符为
字符代表正确的位置。这构成了一个简单的范围
构建内部类。

除了该构造之外的任何东西,破折号都是文字。

例如[a-c-m-o]表示a,b,c,m,n,o和 -

因此,开头或结尾的短划线不能解析作为范围操作符,
如果它在范围之间或在一个范围之间(例如:[a-d-tovz]) 当然在开始或结束时它更容易 确保它不被用作范围运营商。

与往常一样,在课堂上转义的任何内容都被视为文字,财产或
控制代码。

此外,属性不能是范围构造的左/右侧。

Java还有其他一些特殊的类构造,例如联合运算符和
嵌套类,但我认为范围运算符功能主要是
所有引擎都一样。