【问题标题】:Comparing 2 Regular Expression Strings比较 2 个正则表达式字符串
【发布时间】:2014-07-01 11:52:42
【问题描述】:

我正在编写一个迁移实用程序,其中一个转换的一部分是测试一对正则表达式。例如,一些测试将是:

+-------+-------+-------+
| Left  | Right | Match |
+-------+-------+-------+
| (.)01 | 101   | Yes   |
+-------+-------+-------+
| (.)02 | 101   | No    |
+-------+-------+-------+
| 101   | 101   | Yes   |
+-------+-------+-------+
| 201   | (.)01 | Yes   |
+-------+-------+-------+
| (.)01 | 2(.)1 | Yes   |
+-------+-------+-------+

目前,我的测试使用.matches逐个测试,当只有一侧是正则表达式时有效,但当双方都有一个时(即示例的最后一行),它返回false什么时候应该返回 true。

那么,我怎样才能得到最后一个例子的肯定比较结果呢?

【问题讨论】:

  • 怎么最后一个返回Yes应该是No
  • 因为Left的第一个字符是wild,而Right的第二个字符是wild
  • 但最后一个字符不匹配
  • 现在说得通了:)
  • 为什么(.)01 会匹配2(.)1?例如 (.)01 匹配 9012(.)1 匹配 281901281 非常不同。请更详细地说明您正在努力实现的目标以及您迄今为止所做的尝试。

标签: java regex match


【解决方案1】:

您使用错误的正则表达式。您应该使用正则表达式将字符串与给定的正则表达式匹配,而不是相互测试正则表达式。

一个正则表达式表示一组可能的匹配:(.)01 匹配 a01301$01 等...

因此,当您匹配该集合中的一项时,这样做是有意义的,例如$01 与正则表达式匹配。

在您的最后一种情况下,您尝试将正则表达式与正则表达式匹配,这很愚蠢。哪个正则表达式是您的源,哪个字符串是您的目标?如果第一个正则表达式是您的源,201 匹配它,但也匹配 101#01 等...但是根据第二个正则表达式这是不正确的,它匹配像 201 这样的项目,但也匹配 @ 987654332@ 和291。因此,它们不应被视为“相互匹配”。

看看这个维恩图:

您的上一次正则表达式比赛有两个正则表达式互相争斗。 第一个正则表达式由圆圈 A 表示。第二个正则表达式由圆圈 B 表示。

有一些元素(嗯,只是201)既在圆A 又在圆B 中(由深色both A & B 指出)。你认为这些圈子是匹配的吗?我当然不会。如果他们完全覆盖对方,我会的。

但是这些圈子完全相互覆盖的唯一方法(意味着圈子 A 中的所有内容都在圈子 B 中,而圈子 B 中的所有内容都在圈子 A 中)是,如果两个正则表达式完全相同!喜欢(.)01 和......(.)01!这是唯一可能的匹配,但如果您将一个像正则表达式和一个像字符串一样对待,它仍然无法正常工作。

编辑如果您只想确定这是否是至少一个常见匹配项,这可能会有所帮助:https://stackoverflow.com/a/17957180/1283166

【讨论】:

  • OP 不想检查A == B 而是检查AB 的交集是否不为空(如果存在一些常见的匹配项)。
【解决方案2】:

在这种情况下,您不需要任何正则表达式比较。一个简单的算法就可以了。

从两个字符串中删除基于通配符的字符,然后使用equals()方法检查。

如果每个字符串中出现的通配符不超过一次,这样的方法可能会对您有所帮助:

    final String WILD_CARD = "(.)";
    String str1 ="(.)01";
    String str2 ="2(.)1";
    int index = -1;
    if((index=str1.indexOf(WILD_CARD))!=-1) {
        str1 = str1.replace(WILD_CARD, "");
        str2 = str2.replace(String.valueOf(str2.charAt(index)),"");
    }

    if((index=str2.indexOf(WILD_CARD))!=-1) {
        str2 = str2.replace(WILD_CARD, "");
        str1 = str1.replace(String.valueOf(str1.charAt(index)), "");
    } 

    if(str1.equals(str2)) {
        System.out.println("Yes");
    } else {
        System.out.println("No");
    }

【讨论】:

  • 如果双方都有(.*)怎么办?
  • 我本可以编写完整的实现,但我故意将其留给 OP 来实现。
  • 此解决方案不正确。如果 str1 是 1(*)1 而 str2 是 1(*)1,那么第一个 if 块会将它们修改为 str1 = 11 str2 = 1*)1。第二个 if 语句什么都不做,最后一个会得出结论它们不相等。如果任一字符串中有多个(.),也会出现错误。或者如果 str1 = (.)11 str2 = 111 因为 str2.replace 会将 str2 中的所有字符串替换为空字符串。
  • @Alderath 我同意你的看法。我已经说过这不是一个完整的实现。这可能是实现 OP 所需的一种方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-10
  • 1970-01-01
  • 2011-08-01
  • 1970-01-01
  • 2017-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多