【问题标题】:Java Regex: Why is \177 escape code invalid?Java Regex:为什么 \177 转义码无效?
【发布时间】:2016-12-09 12:22:03
【问题描述】:

我正在使用常见的正则表达式来验证电子邮件。模式是这样的:

(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*")@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$)|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$

以防万一,我确实在 java 中添加了所有 \ 转义,所以这是 java 评估的最终模式。它适用于普通的在线正则表达式评估器,但在 Java 中运行时会抛出

java.util.regex.PatternSyntaxException:索引 103 附近的转义序列非法/不受支持

这是 \177 代码。为什么会这样,为什么该代码是非法的,为什么它可以在在线验证器中工作?

【问题讨论】:

  • 你想通过\177代表什么?

标签: java regex


【解决方案1】:

The javadoc of Pattern在这里给你答案;引用:

\0n     The character with octal value 0n (0 <= n <= 7)
\0nn    The character with octal value 0nn (0 <= n <= 7)
\0mnn   The character with octal value 0mnn (0 <= m <= 3, 0 <= n <= 7)

八进制转义序列出现的唯一有效方式是上述。

如果你写\1xx,无论xx,这将被解释为\1然后xx,其中\1是对正则表达式的第一个捕获组的反向引用......

除了在您的情况下,索引 103 位于:

...37!#-\[\]-\177]|\\
             ^^ HERE

你在一个角色类中;并且您不能在字符类中使用反向引用。因此,正则表达式引擎试图将其解释为转义序列,如上所述,这是非法的。因此,消息。

将其替换为\0177,您的问题将得到解决。

附带说明,使用正则表达式验证电子邮件虽然很常见,但也是一个非常糟糕的主意。改用 javax.mail,它可以使用InternetAddress 验证邮件地址。

[进一步说明:虽然上面的链接指向 Java EE,但实际上您可以将 javamail 作为独立 jar 添加到您的项目中;快速的 Maven 搜索会告诉你]

【讨论】:

  • InternetAddress 让我害怕的部分是 validate 的 javadoc:“当前的实现检查了许多但不是全部的语法规则。”有了这个正则表达式,我们至少在多个平台上使用相同的模式标准化了评估。
  • @WilliamMartínezPomares 即使这样,您也应该使用它,而不是您在“某处”找到的正则表达式。 javamail 的开发人员非常了解他们的工作,以至于实际上无法验证 RFC 2822 的情况几乎为零。并且肯定比您在那里找到的几乎所有正则表达式都要好。
【解决方案2】:

内联正则表达式验证器往往会产生误导,因为有许多不同风格的正则表达式。您需要一个 Java 正则表达式,但您的验证器显然正在测试一种相关但不同的风格。

针对您的具体问题:正如您从the documentation for java.util.regex.Pattern 中看到的,八进制转义必须以\0 开头,但之后最多可以包含三位数字。所以,把\177改成\0177

【讨论】:

    【解决方案3】:

    在 Java 类之外,将八进制视为 \0377 以将其与 a 区分开来
    反向引用。

    其他引擎将采用\377 形式,但使用内部捕获组
    在这一点上识别以将其与反向引用区分开来。
    这些其他引擎无法识别类中的 \nnn 表单,
    但为此提供一个八进制括号形式\o{nnn}

    据我所知,你可以试试 \0377 inside classes 看看是否
    那行得通,否则我不知道Java是否在类中识别八进制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-21
      • 2022-10-24
      • 2016-07-15
      • 1970-01-01
      • 2015-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多