为什么我的负面观察不适用于Java?

时间:2017-09-15 20:29:40

标签: java regex

我试图使用负面的lookbehind来对字符串进行一些匹配,这些字符串将从我们所讨论的另一个系统发送到系统中。我搜索过类似的问题,但我无法根据之前发布的任何问题解决此问题。

这可以按预期工作

Pattern pattern = Pattern.compile ("^(?<!SyCs-)([A-Za-z\\s\\d]+)$");
String s = "SyCs-a";

Assert.assertEquals (false, pattern.matcher (s).matches ());

这是问题所在:使用当前的正则表达式,以下也返回false,这是有道理的,因为' - '(破折号)不是允许值的一部分([A-Za-z \ s \ d] +)即可。

s = "TyCs-a";

Assert.assertEquals (false, pattern.matcher (s).matches ());

但是,我需要返回true,但是当我将破折号添加到允许值时,第一个String也返回true。

没有破折号

Pattern pattern = Pattern.compile ("^(?<!SyCs-)([A-Za-z\\s\\d]+)$");
String s = "SyCs-a";

Assert.assertEquals (false, pattern.matcher (s).matches ());

s = "TyCs-a";

Assert.assertEquals (false, pattern.matcher (s).matches ());

使用破折号

Pattern pattern = Pattern.compile ("^(?<!SyCs-)([A-Za-z\\s\\d-]+)$");
String s = "SyCs-a";

Assert.assertEquals (true, pattern.matcher (s).matches ());

s = "TyCs-a";

Assert.assertEquals (true, pattern.matcher (s).matches ());

我试图让+不贪婪+?但这根本不会改变结果。

有什么建议吗?

以下是我用来验证正则表达式的整套测试

@Test
public void testNegativeLookBehind () {
    Pattern pattern = Pattern.compile ("^(?<!SyCs-)([A-Za-z\\s\\d]+)$");
    String s = "SyCs-a";

    Assert.assertEquals (false, pattern.matcher (s).matches ());

    s = "SyCs-b";

    Assert.assertEquals (false, pattern.matcher (s).matches ());

    s = "SyCs-ab";

    Assert.assertEquals (false, pattern.matcher (s).matches ());

    s = "SyCs-ab1";

    Assert.assertEquals (false, pattern.matcher (s).matches ());

    s = "SyCs-abZ";

    Assert.assertEquals (false, pattern.matcher (s).matches ());

    s = "SyCs- abZ";

    Assert.assertEquals (false, pattern.matcher (s).matches ());

    s = "SyCs ab1";

    Assert.assertEquals (true, pattern.matcher (s).matches ());

    /*s = "TyCs-a";

    Assert.assertEquals (true, pattern.matcher (s).matches ());

    s = "SyCr-a";

    Assert.assertEquals (true, pattern.matcher (s).matches ());
    */
    s = "ab";

    Assert.assertEquals (true, pattern.matcher (s).matches ());

    s = "sab";

    Assert.assertEquals (true, pattern.matcher (s).matches ());

    s = "Csab";

    Assert.assertEquals (true, pattern.matcher (s).matches ());

    s = "yCsab";

    Assert.assertEquals (true, pattern.matcher (s).matches ());

    s = "SyCsab";

    Assert.assertEquals (true, pattern.matcher (s).matches ());
}

1 个答案:

答案 0 :(得分:3)

如果当前位置左侧有(?<!SyCs-) CyCs-^是一个负面的后视,会导致匹配失败。由于当前位置是字符串的开头(String pat = "^(?!SyCs-)[A-Za-z\\s\\d-]+$"; ^^^^^^^^^ ),因此后备总是返回 true 并且无用。

你需要在这里使用前瞻,而不是一个后视:

^(?!SyCs-)

请参阅regex demo

SyCs-将检查字符串是否以.matches()开头,如果是,则匹配将失败。

请注意,如果您使用带^方法的模式,则可能会忽略模式中的$和{{1}}锚点,因为该方法需要完整的字符串匹配。